From 569333cdedc3a5926164c4890d974fa5a6f8ed56 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Thu, 2 May 2024 22:48:49 +0300 Subject: [PATCH] refactor tree iterator --- src/eptree.cpp | 52 ++--- src/eptree.h | 79 ++----- src/free_blocks_allocator.cpp | 27 +-- src/free_blocks_tree.cpp | 54 ++--- src/free_blocks_tree.h | 84 ++------ src/free_blocks_tree_bucket.cpp | 66 ++---- src/free_blocks_tree_bucket.h | 97 ++------- src/ftree.cpp | 9 +- src/ftree.h | 8 +- src/ftrees.cpp | 64 ++---- src/ftrees.h | 84 ++------ src/ptree.cpp | 9 +- src/ptree.h | 250 ++++++++-------------- src/ptree_node.h | 262 +++++------------------- src/rtree.cpp | 9 +- src/rtree.h | 8 +- tests/eptree_tests.cpp | 12 +- tests/free_blocks_tree_bucket_tests.cpp | 28 +-- tests/free_blocks_tree_tests.cpp | 28 +-- tests/ftree_tests.cpp | 18 +- tests/ftrees_tests.cpp | 25 +-- tests/rtree_tests.cpp | 2 +- 22 files changed, 365 insertions(+), 910 deletions(-) diff --git a/src/eptree.cpp b/src/eptree.cpp index 8f2dbb6..072b8a6 100644 --- a/src/eptree.cpp +++ b/src/eptree.cpp @@ -9,7 +9,7 @@ #include "eptree.h" -EPTreeConstIterator& EPTreeConstIterator::operator++() { +EPTreeIterator& EPTreeIterator::operator++() { assert(!is_end()); auto rnode = nodes_.rbegin(); while ((++rnode->iterator).is_end()) { @@ -19,53 +19,31 @@ EPTreeConstIterator& EPTreeConstIterator::operator++() { return *this; // end } } - uint32_t node_block_number = rnode->iterator->value; + uint32_t node_block_number = (*rnode->iterator).value; for (auto node = rnode.base(); node != nodes_.end(); ++node) { *node = {allocator_->LoadAllocatorBlock(node_block_number)}; node->iterator = node->node->begin(); - node_block_number = node->iterator->value; + node_block_number = (*node->iterator).value; } return *this; } -EPTreeConstIterator& EPTreeConstIterator::operator--() { +EPTreeIterator& EPTreeIterator::operator--() { assert(!is_begin()); auto rnode = nodes_.rbegin(); for (; rnode->iterator.is_begin(); rnode++) { if (rnode == nodes_.rend()) return *this; // begin } - uint32_t node_block_number = (--rnode->iterator)->value; + uint32_t node_block_number = (*--rnode->iterator).value; for (auto node = rnode.base(); node != nodes_.end(); ++node) { *node = {allocator_->LoadAllocatorBlock(node_block_number)}; node->iterator = node->node->end(); - node_block_number = (--node->iterator)->value; + node_block_number = (*--node->iterator).value; } return *this; } -EPTreeConstIterator EPTreeConstIterator::operator++(int) { - EPTreeConstIterator tmp(*this); - ++(*this); - return tmp; -} - -EPTreeConstIterator EPTreeConstIterator::operator--(int) { - EPTreeConstIterator tmp(*this); - --(*this); - return tmp; -} - -EPTreeIterator& EPTreeIterator::operator++() { - base::operator++(); - return *this; -} - -EPTreeIterator& EPTreeIterator::operator--() { - base::operator--(); - return *this; -} - EPTreeIterator EPTreeIterator::operator++(int) { EPTreeIterator tmp(*this); ++(*this); @@ -96,7 +74,7 @@ bool EPTree::insert(const iterator::value_type& key_value) { auto depth = node_level->tree_header()->depth.value(); // Where to split the level auto split_point = node_level->middle(); - key_type split_point_key = split_point->key; + key_type split_point_key = (*split_point).key; // Alloc new right side tree auto right_block_number = AllocBlockForTree(node_level->tree_header()->block_number.value(), allocated_extents); RTree new_right(allocator_->LoadAllocatorBlock(right_block_number, /*new_block=*/true)); @@ -135,7 +113,7 @@ bool EPTree::insert(const iterator::value_type& key_value) { return true; } -bool EPTree::insert(const RTree::const_iterator& it_start, const RTree::const_iterator& it_end) { +bool EPTree::insert(const RTree::iterator& it_start, const RTree::iterator& it_end) { for (const auto& val : std::ranges::subrange(it_start, it_end)) { if (!insert(val)) return false; @@ -143,7 +121,7 @@ bool EPTree::insert(const RTree::const_iterator& it_start, const RTree::const_it return true; } -void EPTree::erase(const const_iterator& pos, std::vector& blocks_to_delete) { +void EPTree::erase(const iterator& pos, std::vector& blocks_to_delete) { // Erase from each node for (auto& [node_level, node_it] : std::views::reverse(pos.nodes())) { node_level->erase(node_it); @@ -175,38 +153,38 @@ uint32_t EPTree::AllocBlockForTree(uint32_t near, std::vectorFindSmallestFreeBlockExtent(near, allocated); } -EPTree::iterator EPTree::begin_impl() const { +EPTree::iterator EPTree::begin() const { std::vector nodes; nodes.reserve(tree_header()->depth.value()); assert(tree_header()->depth.value() >= 1); for (int i = 0; i < tree_header()->depth.value(); i++) { assert(i == 0 || !nodes.back().iterator.is_end()); - iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock(nodes.back().iterator->value)}; + iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock((*nodes.back().iterator).value)}; node.iterator = node.node->begin(); nodes.push_back(std::move(node)); } return {allocator_, std::move(nodes)}; } -EPTree::iterator EPTree::end_impl() const { +EPTree::iterator EPTree::end() const { std::vector nodes; nodes.reserve(tree_header()->depth.value()); assert(tree_header()->depth.value() >= 1); for (int i = 0; i < tree_header()->depth.value(); i++) { assert(i == 0 || !nodes.back().iterator.is_begin()); - iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock((--nodes.back().iterator)->value)}; + iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock((*--nodes.back().iterator).value)}; node.iterator = node.node->end(); nodes.push_back(std::move(node)); } return {allocator_, std::move(nodes)}; } -EPTree::iterator EPTree::find_impl(key_type key, bool exact_match) const { +EPTree::iterator EPTree::find(key_type key, bool exact_match) const { std::vector nodes; nodes.reserve(tree_header()->depth.value()); for (int i = 0; i < tree_header()->depth.value(); i++) { assert(i == 0 || !nodes.back().iterator.is_end()); - iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock((nodes.back().iterator)->value)}; + iterator::node_info node{i == 0 ? block() : allocator_->LoadAllocatorBlock((*nodes.back().iterator).value)}; node.iterator = node.node->find(key, exact_match && i + 1 == tree_header()->depth.value()); nodes.push_back(std::move(node)); } diff --git a/src/eptree.h b/src/eptree.h index df1dd56..3ca4a4d 100644 --- a/src/eptree.h +++ b/src/eptree.h @@ -14,36 +14,29 @@ #include "free_blocks_allocator.h" #include "rtree.h" -class EPTreeConstIterator { +class EPTreeIterator { public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; using value_type = RTree::iterator::value_type; - using const_reference = RTree::iterator::const_reference; - using const_pointer = RTree::iterator::const_pointer; - - using reference = RTree::const_iterator::reference; - using pointer = RTree::const_iterator::const_pointer; + using reference = RTree::iterator::reference; using node_info = node_iterator_info; - EPTreeConstIterator() = default; + EPTreeIterator() = default; - EPTreeConstIterator(FreeBlocksAllocator* allocator, std::vector nodes) + EPTreeIterator(FreeBlocksAllocator* allocator, std::vector nodes) : allocator_(allocator), nodes_(std::move(nodes)) {} reference operator*() const { return *nodes_.back().iterator; } - pointer operator->() const& { return nodes_.back().iterator.operator->(); } - EPTreeConstIterator& operator++(); - EPTreeConstIterator& operator--(); - EPTreeConstIterator operator++(int); - EPTreeConstIterator operator--(int); + EPTreeIterator& operator++(); + EPTreeIterator& operator--(); + EPTreeIterator operator++(int); + EPTreeIterator operator--(int); - bool operator==(const EPTreeConstIterator& other) const { - return nodes_.back().iterator == other.nodes_.back().iterator; - } + bool operator==(const EPTreeIterator& other) const { return nodes_.back().iterator == other.nodes_.back().iterator; } std::vector& nodes() { return nodes_; }; const std::vector& nodes() const { return nodes_; }; @@ -58,67 +51,24 @@ class EPTreeConstIterator { std::vector nodes_; }; -static_assert(std::bidirectional_iterator); - -class EPTreeIterator : public EPTreeConstIterator { - public: - using base = EPTreeConstIterator; - - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = base::difference_type; - using value_type = base::value_type; - - using reference = RTree::iterator::reference; - using pointer = RTree::iterator::pointer; - - using node_info = base::node_info; - - EPTreeIterator() = default; - - EPTreeIterator(FreeBlocksAllocator* allocator, std::vector nodes) : base(allocator, std::move(nodes)) {} - - reference operator*() const { return *nodes().back().iterator; } - pointer operator->() const& { return nodes().back().iterator.operator->(); } - - EPTreeIterator& operator++(); - EPTreeIterator& operator--(); - EPTreeIterator operator++(int); - EPTreeIterator operator--(int); - - bool operator==(const EPTreeIterator& other) const { return base::operator==(other); } -}; static_assert(std::bidirectional_iterator); class EPTree : public EPTreeBlock { public: using iterator = EPTreeIterator; - using const_iterator = EPTreeConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; EPTree(FreeBlocksAllocator* allocator) : EPTreeBlock(allocator->root_block()), allocator_(allocator) {} void Init(uint32_t block_number); - iterator begin() { return begin_impl(); } - iterator end() { return end_impl(); } - const_iterator begin() const { return begin_impl(); } - const_iterator end() const { return end_impl(); } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } - - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } + iterator begin() const; + iterator end() const; - iterator find(key_type key, bool exact_match = true) { return find_impl(key, exact_match); } - const_iterator find(key_type key, bool exact_match = true) const { return find_impl(key, exact_match); } + iterator find(key_type key, bool exact_match = true) const; bool insert(const iterator::value_type& key_value); - bool insert(const RTree::const_iterator& it_start, const RTree::const_iterator& it_end); - void erase(const const_iterator& pos, std::vector& blocks_to_delete); + bool insert(const RTree::iterator& it_start, const RTree::iterator& it_end); + void erase(const iterator& pos, std::vector& blocks_to_delete); bool erase(key_type key, std::vector& blocks_to_delete); private: @@ -130,3 +80,4 @@ class EPTree : public EPTreeBlock { FreeBlocksAllocator* allocator_; }; +static_assert(std::ranges::bidirectional_range); diff --git a/src/free_blocks_allocator.cpp b/src/free_blocks_allocator.cpp index 21052ef..d5341ab 100644 --- a/src/free_blocks_allocator.cpp +++ b/src/free_blocks_allocator.cpp @@ -164,9 +164,10 @@ void FreeBlocksAllocator::AddFreeBlocksForSize(FreeBlocksRangeInfo range, size_t // 1. It ends exactly at this range start. // 2. This range start isn't aligned to one size up bucket block. // 3. OR joining those ranges will still be smaller than one size up bucket - if (pos->end_block_number() == range_in_size.block_number && + FreeBlocksExtentInfo before_pos = *pos; + if (before_pos.end_block_number() == range_in_size.block_number && (!is_aligned_pow2(range_in_size.block_number, next_size_pow2) || - pos->blocks_count() + range_in_size.blocks_count < next_size_blocks_count)) { + before_pos.blocks_count + range_in_size.blocks_count < next_size_blocks_count)) { join_before = *pos; join_before_iter = pos; range_in_size.block_number = join_before->block_number; @@ -177,12 +178,12 @@ void FreeBlocksAllocator::AddFreeBlocksForSize(FreeBlocksRangeInfo range, size_t // 1. It start exactly at this range end. // 2. This range end isn't aligned to one size up bucket block. // 3. OR joining those ranges will still be smaller than one size up bucket - if (pos->block_number() <= range_in_size.block_number) // We could be at begin() before + if (before_pos.block_number <= range_in_size.block_number) // We could be at begin() before ++pos; - assert(pos.is_end() || pos->block_number() > range_in_size.block_number); - if (!pos.is_end() && pos->block_number() == range_in_size.end_block_number() && + assert(pos.is_end() || (*pos).block_number() > range_in_size.block_number); + if (!pos.is_end() && (*pos).block_number() == range_in_size.end_block_number() && (!is_aligned_pow2(range_in_size.end_block_number(), next_size_pow2) || - pos->blocks_count() + range_in_size.blocks_count < next_size_blocks_count)) { + (*pos).blocks_count() + range_in_size.blocks_count < next_size_blocks_count)) { FreeBlocksExtentInfo join_after = *pos; range_in_size.blocks_count += join_after.blocks_count; // We give up on the optimization that is done in the original logic (just update the join after block number to @@ -211,7 +212,7 @@ void FreeBlocksAllocator::AddFreeBlocksForSize(FreeBlocksRangeInfo range, size_t sub_range.blocks_count / size_blocks_count <= 0x10); auto new_value = static_cast(sub_range.blocks_count / size_blocks_count - 1); if (join_before && sub_range.block_number == range_in_size.block_number) { - join_before_iter->value = new_value; + (*join_before_iter).value = new_value; } else { // Don't use pos to insert because: // 1. Our find may go back so it isn't the exact location to insert it. @@ -282,14 +283,14 @@ void FreeBlocksAllocator::RecreateEPTreeIfNeeded() { // Already trivial return; } - auto last = eptree.rbegin(); - if (last->key || last->value != 2) + auto last = eptree.end()--; + if ((*last).key || (*last).value != 2) return; - uint32_t last_value = last->value; + uint32_t last_value = (*last).value; assert(last_value == 2); std::vector blocks_to_delete; // eptree is empty (aka have only initial FTreee), resize it to one eptree - auto nodes = last.base().nodes(); + auto nodes = last.nodes(); for (auto& [node_level, node_it] : std::views::reverse(nodes)) { if (node_level->header() == &eptree.tree_header()->current_tree) { // this is the root, reinitialize it @@ -308,13 +309,13 @@ bool FreeBlocksAllocator::IsRangeIsFree(FreeBlocksRangeInfo range) { if (pos.is_end()) return false; // Check intersection with the free range before us. - if (range.block_number >= pos->block_number() && range.block_number < pos->end_block_number()) + if (range.block_number >= (*pos).block_number() && range.block_number < (*pos).end_block_number()) return true; ++pos; if (pos.is_end()) return false; // Check intersection with the free range after us. - return pos->block_number() >= range.block_number && pos->block_number() < range.end_block_number(); + return (*pos).block_number() >= range.block_number && (*pos).block_number() < range.end_block_number(); } std::optional> FreeBlocksAllocator::AllocBlocks(uint32_t chunks_count, diff --git a/src/free_blocks_tree.cpp b/src/free_blocks_tree.cpp index ed45ce7..3699cdb 100644 --- a/src/free_blocks_tree.cpp +++ b/src/free_blocks_tree.cpp @@ -7,7 +7,7 @@ #include "free_blocks_tree.h" -FreeBlocksTreeConstIterator& FreeBlocksTreeConstIterator::operator++() { +FreeBlocksTreeIterator& FreeBlocksTreeIterator::operator++() { assert(!is_end()); ++ftrees_.iterator; // support empty ftrees? @@ -17,13 +17,13 @@ FreeBlocksTreeConstIterator& FreeBlocksTreeConstIterator::operator++() { return *this; // end } - ftrees_ = {allocator_->LoadAllocatorBlock(eptree_.iterator->value)}; + ftrees_ = {allocator_->LoadAllocatorBlock((*eptree_.iterator).value)}; ftrees_.iterator = ftrees_.node->begin(); } return *this; } -FreeBlocksTreeConstIterator& FreeBlocksTreeConstIterator::operator--() { +FreeBlocksTreeIterator& FreeBlocksTreeIterator::operator--() { assert(!is_begin()); // support empty ftrees? while (ftrees_.iterator.is_begin()) { @@ -31,35 +31,13 @@ FreeBlocksTreeConstIterator& FreeBlocksTreeConstIterator::operator--() { return *this; // begin } - ftrees_ = {allocator_->LoadAllocatorBlock((--eptree_.iterator)->value)}; + ftrees_ = {allocator_->LoadAllocatorBlock((*--eptree_.iterator).value)}; ftrees_.iterator = ftrees_.node->end(); } --ftrees_.iterator; return *this; } -FreeBlocksTreeConstIterator FreeBlocksTreeConstIterator::operator++(int) { - FreeBlocksTreeConstIterator tmp(*this); - ++(*this); - return tmp; -} - -FreeBlocksTreeConstIterator FreeBlocksTreeConstIterator::operator--(int) { - FreeBlocksTreeConstIterator tmp(*this); - --(*this); - return tmp; -} - -FreeBlocksTreeIterator& FreeBlocksTreeIterator::operator++() { - FreeBlocksTreeConstIterator::operator++(); - return *this; -} - -FreeBlocksTreeIterator& FreeBlocksTreeIterator::operator--() { - FreeBlocksTreeConstIterator::operator--(); - return *this; -} - FreeBlocksTreeIterator FreeBlocksTreeIterator::operator++(int) { FreeBlocksTreeIterator tmp(*this); ++(*this); @@ -72,11 +50,11 @@ FreeBlocksTreeIterator FreeBlocksTreeIterator::operator--(int) { return tmp; } -FreeBlocksTree::iterator FreeBlocksTree::begin_impl() const { +FreeBlocksTree::iterator FreeBlocksTree::begin() const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->begin(); assert(!eptree.iterator.is_end()); - iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock(eptree.iterator->value)}}; + iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock((*eptree.iterator).value)}}; ftrees.iterator = ftrees.node->begin(); while (ftrees.iterator.is_end()) { if ((++eptree.iterator).is_end()) { @@ -85,35 +63,35 @@ FreeBlocksTree::iterator FreeBlocksTree::begin_impl() const { return {allocator_, std::move(eptree), std::move(ftrees)}; } - ftrees = {{allocator_->LoadAllocatorBlock(eptree.iterator->value)}}; + ftrees = {{allocator_->LoadAllocatorBlock((*eptree.iterator).value)}}; ftrees.iterator = ftrees.node->begin(); } return {allocator_, std::move(eptree), std::move(ftrees)}; } -FreeBlocksTree::iterator FreeBlocksTree::end_impl() const { +FreeBlocksTree::iterator FreeBlocksTree::end() const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->end(); assert(!eptree.iterator.is_begin()); --eptree.iterator; // EPTree size should always be >= 1 - iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock(eptree.iterator->value)}}; + iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock((*eptree.iterator).value)}}; ftrees.iterator = ftrees.node->end(); return {allocator_, std::move(eptree), std::move(ftrees)}; } -FreeBlocksTree::iterator FreeBlocksTree::find_impl(key_type key, bool exact_match) const { +FreeBlocksTree::iterator FreeBlocksTree::find(key_type key, bool exact_match) const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->find(key, false); if (eptree.iterator.is_end()) - return end_impl(); - iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock(eptree.iterator->value)}}; + return end(); + iterator::ftrees_node_info ftrees{{allocator_->LoadAllocatorBlock((*eptree.iterator).value)}}; ftrees.iterator = ftrees.node->find(key, exact_match); - if (!ftrees.iterator.is_end() && key >= ftrees.iterator->key) { + if (!ftrees.iterator.is_end() && key >= (*ftrees.iterator).key) { return {allocator_, std::move(eptree), std::move(ftrees)}; } // If FTrees is empty or our key is smaller than the first key, go to previous node with value if (exact_match) { - return end_impl(); + return end(); } if (!ftrees.iterator.is_begin()) { --ftrees.iterator; @@ -122,7 +100,7 @@ FreeBlocksTree::iterator FreeBlocksTree::find_impl(key_type key, bool exact_matc auto orig_eptree_it = eptree.iterator; // Go backward to search for value while (!eptree.iterator.is_begin()) { - iterator::ftrees_node_info nftrees{{allocator_->LoadAllocatorBlock((--eptree.iterator)->value)}}; + iterator::ftrees_node_info nftrees{{allocator_->LoadAllocatorBlock((*--eptree.iterator).value)}}; nftrees.iterator = nftrees.node->find(key, exact_match); if (!nftrees.iterator.is_end()) { ftrees = std::move(nftrees); @@ -136,7 +114,7 @@ FreeBlocksTree::iterator FreeBlocksTree::find_impl(key_type key, bool exact_matc } // Go forward to search.. while (!(++eptree.iterator).is_end()) { - ftrees = {{allocator_->LoadAllocatorBlock(eptree.iterator->value)}}; + ftrees = {{allocator_->LoadAllocatorBlock((*eptree.iterator).value)}}; ftrees.iterator = ftrees.node->begin(); if (!ftrees.iterator.is_end()) { // Found value diff --git a/src/free_blocks_tree.h b/src/free_blocks_tree.h index 9bc1a69..396568d 100644 --- a/src/free_blocks_tree.h +++ b/src/free_blocks_tree.h @@ -14,7 +14,7 @@ #include "ftrees.h" #include "tree_utils.h" -class FreeBlocksTreeConstIterator { +class FreeBlocksTreeIterator { public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; @@ -22,29 +22,24 @@ class FreeBlocksTreeConstIterator { using value_type = typename FTrees::iterator::value_type; using ref_type = typename FTrees::iterator::ref_type; - using const_reference = value_type; - using const_pointer = ref_type*; - - using reference = const_reference; - using pointer = const_pointer; + using reference = value_type; using eptree_node_info = node_iterator_info; using ftrees_node_info = node_iterator_info; - FreeBlocksTreeConstIterator() = default; - FreeBlocksTreeConstIterator(FreeBlocksAllocator* allocator, eptree_node_info eptree, ftrees_node_info ftrees) + FreeBlocksTreeIterator() = default; + FreeBlocksTreeIterator(FreeBlocksAllocator* allocator, eptree_node_info eptree, ftrees_node_info ftrees) : allocator_(allocator), eptree_(std::move(eptree)), ftrees_(std::move(ftrees)) {} - reference operator*() const { return *operator->(); } - pointer operator->() const& { return reinterpret_cast(ftrees_.iterator.operator->()); } + reference operator*() const { return *ftrees_.iterator; } - FreeBlocksTreeConstIterator& operator++(); - FreeBlocksTreeConstIterator& operator--(); + FreeBlocksTreeIterator& operator++(); + FreeBlocksTreeIterator& operator--(); - FreeBlocksTreeConstIterator operator++(int); - FreeBlocksTreeConstIterator operator--(int); + FreeBlocksTreeIterator operator++(int); + FreeBlocksTreeIterator operator--(int); - bool operator==(const FreeBlocksTreeConstIterator& other) const { return ftrees_.iterator == other.ftrees_.iterator; } + bool operator==(const FreeBlocksTreeIterator& other) const { return ftrees_.iterator == other.ftrees_.iterator; } eptree_node_info& eptree() { return eptree_; } const eptree_node_info& eptree() const { return eptree_; } @@ -60,69 +55,20 @@ class FreeBlocksTreeConstIterator { eptree_node_info eptree_; ftrees_node_info ftrees_; }; - -class FreeBlocksTreeIterator : public FreeBlocksTreeConstIterator { - public: - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = FreeBlocksTreeConstIterator::difference_type; - - using value_type = FreeBlocksTreeConstIterator::value_type; - using ref_type = FreeBlocksTreeConstIterator::ref_type; - - using reference = ref_type; - using pointer = ref_type*; - - using eptree_node_info = FreeBlocksTreeConstIterator::eptree_node_info; - using ftrees_node_info = FreeBlocksTreeConstIterator::ftrees_node_info; - - FreeBlocksTreeIterator() = default; - FreeBlocksTreeIterator(FreeBlocksAllocator* allocator, eptree_node_info eptree, ftrees_node_info ftrees) - : FreeBlocksTreeConstIterator(allocator, std::move(eptree), std::move(ftrees)) {} - - reference operator*() const { return *operator->(); } - pointer operator->() const& { return const_cast(FreeBlocksTreeConstIterator::operator->()); } - - FreeBlocksTreeIterator& operator++(); - FreeBlocksTreeIterator& operator--(); - - FreeBlocksTreeIterator operator++(int); - FreeBlocksTreeIterator operator--(int); - - bool operator==(const FreeBlocksTreeIterator& other) const { return FreeBlocksTreeConstIterator::operator==(other); } -}; - -static_assert(std::bidirectional_iterator); static_assert(std::bidirectional_iterator); class FreeBlocksTree { public: - using iterator = FreeBlocksTreeConstIterator; - using const_iterator = FreeBlocksTreeConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; + using iterator = FreeBlocksTreeIterator; FreeBlocksTree(FreeBlocksAllocator* allocator) : allocator_(allocator) {} - iterator begin() { return begin_impl(); } - iterator end() { return end_impl(); } - const_iterator begin() const { return begin_impl(); } - const_iterator end() const { return end_impl(); } + iterator begin() const; + iterator end() const; - reverse_iterator rbegin() { return reverse_iterator{end()}; } - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } - - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - iterator find(key_type key, bool exact_match = true) { return find_impl(key, exact_match); } - const_iterator find(key_type key, bool exact_match = true) const { return find_impl(key, exact_match); } + iterator find(key_type key, bool exact_match = true) const; private: - iterator begin_impl() const; - iterator end_impl() const; - iterator find_impl(key_type key, bool exact_match = true) const; - FreeBlocksAllocator* allocator_; }; +static_assert(std::ranges::bidirectional_range); diff --git a/src/free_blocks_tree_bucket.cpp b/src/free_blocks_tree_bucket.cpp index 46cbd20..efe0189 100644 --- a/src/free_blocks_tree_bucket.cpp +++ b/src/free_blocks_tree_bucket.cpp @@ -9,7 +9,7 @@ #include -FreeBlocksTreeBucketConstIterator& FreeBlocksTreeBucketConstIterator::operator++() { +FreeBlocksTreeBucketIterator& FreeBlocksTreeBucketIterator::operator++() { assert(!is_end()); ++ftree_.iterator; while (ftree_.iterator.is_end()) { @@ -18,48 +18,26 @@ FreeBlocksTreeBucketConstIterator& FreeBlocksTreeBucketConstIterator::operator++ return *this; // end } - ftree_ = {{allocator_->LoadAllocatorBlock(eptree_.iterator->value), block_size_index_}}; + ftree_ = {{allocator_->LoadAllocatorBlock((*eptree_.iterator).value), block_size_index_}}; ftree_.iterator = ftree_.node->begin(); } return *this; } -FreeBlocksTreeBucketConstIterator& FreeBlocksTreeBucketConstIterator::operator--() { +FreeBlocksTreeBucketIterator& FreeBlocksTreeBucketIterator::operator--() { assert(!is_begin()); while (ftree_.iterator.is_begin()) { if (eptree_.iterator.is_begin()) { return *this; // begin } - ftree_ = {{allocator_->LoadAllocatorBlock((--eptree_.iterator)->value), block_size_index_}}; + ftree_ = {{allocator_->LoadAllocatorBlock((*--eptree_.iterator).value), block_size_index_}}; ftree_.iterator = ftree_.node->end(); } --ftree_.iterator; return *this; } -FreeBlocksTreeBucketConstIterator FreeBlocksTreeBucketConstIterator::operator++(int) { - FreeBlocksTreeBucketConstIterator tmp(*this); - ++(*this); - return tmp; -} - -FreeBlocksTreeBucketConstIterator FreeBlocksTreeBucketConstIterator::operator--(int) { - FreeBlocksTreeBucketConstIterator tmp(*this); - --(*this); - return tmp; -} - -FreeBlocksTreeBucketIterator& FreeBlocksTreeBucketIterator::operator++() { - base::operator++(); - return *this; -} - -FreeBlocksTreeBucketIterator& FreeBlocksTreeBucketIterator::operator--() { - base::operator--(); - return *this; -} - FreeBlocksTreeBucketIterator FreeBlocksTreeBucketIterator::operator++(int) { FreeBlocksTreeBucketIterator tmp(*this); ++(*this); @@ -74,7 +52,7 @@ FreeBlocksTreeBucketIterator FreeBlocksTreeBucketIterator::operator--(int) { bool FreeBlocksTreeBucket::insert(FTree::iterator::value_type key_val) { auto pos = find_for_insert(key_val.key); - if (!pos.is_end() && pos->key == key_val.key) { + if (!pos.is_end() && (*pos).key == key_val.key) { // already in tree return false; } @@ -89,7 +67,7 @@ bool FreeBlocksTreeBucket::insert(iterator& pos, FTree::iterator::value_type key auto old_block = pos.ftree().node->block(); old_block->Detach(); FTrees old_ftrees{old_block}; - uint32_t left_block_number = pos.eptree().iterator->value; + uint32_t left_block_number = (*pos.eptree().iterator).value; auto left_block = allocator_->LoadAllocatorBlock(left_block_number, true); assert(left_block->device_block_number() == old_block->device_block_number()); @@ -100,7 +78,7 @@ bool FreeBlocksTreeBucket::insert(iterator& pos, FTree::iterator::value_type key for (const auto& ftree : old_ftrees.ftrees()) { if (ftree.size() > 0) { auto first = ftree.begin(); - *allocated_extent = {first->key, 1, ftree.index()}; + *allocated_extent = {(*first).key, 1, ftree.index()}; break; } } @@ -130,12 +108,12 @@ bool FreeBlocksTreeBucket::insert(iterator& pos, FTree::iterator::value_type key void FreeBlocksTreeBucket::erase(iterator pos, std::vector& blocks_to_delete) { pos.ftree().node->erase(pos.ftree().iterator); // Check for FTrees deletion, we never delete the first FTree (key zero) - if (!pos.ftree().node->empty() || !pos.eptree().iterator->key) { + if (!pos.ftree().node->empty() || !(*pos.eptree().iterator).key) { return; } if (FTrees(pos.ftree().node->block()).empty()) { // The FTree is the first block for deletion - blocks_to_delete.push_back({pos.eptree().iterator->value, 1}); + blocks_to_delete.push_back({(*pos.eptree().iterator).value, 1}); pos.eptree().node->erase(pos.eptree().iterator, blocks_to_delete); } } @@ -148,11 +126,11 @@ bool FreeBlocksTreeBucket::erase(key_type key, std::vector& return true; } -FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::begin_impl() const { +FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::begin() const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->begin(); assert(!eptree.iterator.is_end()); - iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock(eptree.iterator->value), block_size_index_}}; + iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->begin(); while (ftree.iterator.is_end()) { if ((++eptree.iterator).is_end()) { @@ -161,35 +139,35 @@ FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::begin_impl() const { return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; } - ftree = {{allocator_->LoadAllocatorBlock(eptree.iterator->value), block_size_index_}}; + ftree = {{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->begin(); } return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; } -FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::end_impl() const { +FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::end() const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->end(); assert(!eptree.iterator.is_begin()); --eptree.iterator; // EPTree size should always be >= 1 - iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock(eptree.iterator->value), block_size_index_}}; + iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->end(); return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; } -FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::find_impl(key_type key, bool exact_match) const { +FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::find(key_type key, bool exact_match) const { iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->find(key, false); if (exact_match && eptree.iterator.is_end()) - return end_impl(); - iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock(eptree.iterator->value), block_size_index_}}; + return end(); + iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->find(key, exact_match); - if (!ftree.iterator.is_end() && key >= ftree.iterator->key) { + if (!ftree.iterator.is_end() && key >= (*ftree.iterator).key) { return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; } // If FTree is empty or our key is smaller than the first key, go to previous node with value if (exact_match) - return end_impl(); + return end(); if (!ftree.iterator.is_begin()) { --ftree.iterator; return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; @@ -197,7 +175,7 @@ FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::find_impl(key_type key, boo auto orig_eptree_it = eptree.iterator; // Go backward to search for value while (!eptree.iterator.is_begin()) { - iterator::ftree_node_info nftree{{allocator_->LoadAllocatorBlock((--eptree.iterator)->value), block_size_index_}}; + iterator::ftree_node_info nftree{{allocator_->LoadAllocatorBlock((*--eptree.iterator).value), block_size_index_}}; nftree.iterator = nftree.node->end(); if (!nftree.iterator.is_begin()) { --nftree.iterator; @@ -212,7 +190,7 @@ FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::find_impl(key_type key, boo } // Go forward to search.. while (!(++eptree.iterator).is_end()) { - ftree = {{allocator_->LoadAllocatorBlock(eptree.iterator->value), block_size_index_}}; + ftree = {{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->begin(); if (!ftree.iterator.is_end()) { // Found value @@ -227,7 +205,7 @@ FreeBlocksTreeBucket::iterator FreeBlocksTreeBucket::find_for_insert(key_type ke iterator::eptree_node_info eptree{{allocator_}}; eptree.iterator = eptree.node->find(key, false); assert(!eptree.iterator.is_end()); - iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock((eptree.iterator)->value), block_size_index_}}; + iterator::ftree_node_info ftree{{allocator_->LoadAllocatorBlock((*eptree.iterator).value), block_size_index_}}; ftree.iterator = ftree.node->find(key, false); return {allocator_, block_size_index_, std::move(eptree), std::move(ftree)}; } diff --git a/src/free_blocks_tree_bucket.h b/src/free_blocks_tree_bucket.h index 04d1f6f..d319dfe 100644 --- a/src/free_blocks_tree_bucket.h +++ b/src/free_blocks_tree_bucket.h @@ -14,44 +14,37 @@ #include "ftrees.h" #include "tree_utils.h" -class FreeBlocksTreeBucketConstIterator { +class FreeBlocksTreeBucketIterator { public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; - using value_type = FTrees::const_iterator::value_type; - using ref_type = FTrees::const_iterator::ref_type; + using value_type = FTrees::iterator::value_type; + using ref_type = FTrees::iterator::ref_type; - using const_reference = FTrees::const_iterator::const_reference; - using const_pointer = FTrees::const_iterator::const_pointer; - - using reference = const_reference; - using pointer = const_pointer; + using reference = FTrees::iterator::reference; using eptree_node_info = node_iterator_info; using ftree_node_info = node_iterator_info; - FreeBlocksTreeBucketConstIterator() = default; - FreeBlocksTreeBucketConstIterator(FreeBlocksAllocator* allocator, - size_t block_size_index, - eptree_node_info eptree, - ftree_node_info ftree) + FreeBlocksTreeBucketIterator() = default; + FreeBlocksTreeBucketIterator(FreeBlocksAllocator* allocator, + size_t block_size_index, + eptree_node_info eptree, + ftree_node_info ftree) : allocator_(allocator), block_size_index_(block_size_index), eptree_(std::move(eptree)), ftree_(std::move(ftree)) {} - reference operator*() const { return *operator->(); } - pointer operator->() const& { return reinterpret_cast(ftree_.iterator.operator->()); } + reference operator*() const { return {(*ftree_.iterator)._base}; } - FreeBlocksTreeBucketConstIterator& operator++(); - FreeBlocksTreeBucketConstIterator& operator--(); - FreeBlocksTreeBucketConstIterator operator++(int); - FreeBlocksTreeBucketConstIterator operator--(int); + FreeBlocksTreeBucketIterator& operator++(); + FreeBlocksTreeBucketIterator& operator--(); + FreeBlocksTreeBucketIterator operator++(int); + FreeBlocksTreeBucketIterator operator--(int); - bool operator==(const FreeBlocksTreeBucketConstIterator& other) const { - return ftree_.iterator == other.ftree_.iterator; - } + bool operator==(const FreeBlocksTreeBucketIterator& other) const { return ftree_.iterator == other.ftree_.iterator; } size_t block_size_index() const { return block_size_index_; } @@ -70,68 +63,19 @@ class FreeBlocksTreeBucketConstIterator { eptree_node_info eptree_; ftree_node_info ftree_; }; -static_assert(std::bidirectional_iterator); - -class FreeBlocksTreeBucketIterator : public FreeBlocksTreeBucketConstIterator { - public: - using base = FreeBlocksTreeBucketConstIterator; - - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = base::difference_type; - - using value_type = base::value_type; - using ref_type = base::ref_type; - - using reference = ref_type; - using pointer = ref_type*; - - using eptree_node_info = base::eptree_node_info; - using ftree_node_info = base::ftree_node_info; - - FreeBlocksTreeBucketIterator() = default; - FreeBlocksTreeBucketIterator(FreeBlocksAllocator* allocator, - size_t block_size_index, - eptree_node_info eptree, - ftree_node_info ftree) - : base(allocator, block_size_index, std::move(eptree), std::move(ftree)) {} - - reference operator*() const { return *operator->(); } - pointer operator->() const& { return const_cast(base::operator->()); } - - FreeBlocksTreeBucketIterator& operator++(); - FreeBlocksTreeBucketIterator& operator--(); - FreeBlocksTreeBucketIterator operator++(int); - FreeBlocksTreeBucketIterator operator--(int); - - bool operator==(const FreeBlocksTreeBucketIterator& other) const { return base::operator==(other); } -}; static_assert(std::bidirectional_iterator); class FreeBlocksTreeBucket { public: using iterator = FreeBlocksTreeBucketIterator; - using const_iterator = FreeBlocksTreeBucketConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; FreeBlocksTreeBucket(FreeBlocksAllocator* allocator, size_t block_size_index) : allocator_(allocator), block_size_index_(block_size_index) {} - iterator begin() { return begin_impl(); } - iterator end() { return end_impl(); } - const_iterator begin() const { return begin_impl(); } - const_iterator end() const { return end_impl(); } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } + iterator begin() const; + iterator end() const; - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - iterator find(key_type key, bool exact_match = true) { return find_impl(key, exact_match); } - const_iterator find(key_type key, bool exact_match = true) const { return find_impl(key, exact_match); } + iterator find(key_type key, bool exact_match = true) const; bool insert(FTree::iterator::value_type key_val); bool insert(iterator& pos, FTree::iterator::value_type key_val); @@ -140,13 +84,10 @@ class FreeBlocksTreeBucket { bool erase(key_type key, std::vector& blocks_to_delete); private: - iterator begin_impl() const; - iterator end_impl() const; - iterator find_impl(key_type key, bool exact_match = true) const; - iterator find_for_insert(key_type key) const; FreeBlocksAllocator* allocator_; size_t block_size_index_; }; +static_assert(std::ranges::bidirectional_range); diff --git a/src/ftree.cpp b/src/ftree.cpp index 3fb1d1a..c5fe27a 100644 --- a/src/ftree.cpp +++ b/src/ftree.cpp @@ -8,10 +8,9 @@ #include "ftree.h" template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key) { +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key) { assert(node.begin() <= pos && pos <= node.end()); assert(node.full()); auto res = pos; @@ -30,6 +29,6 @@ PTreeNode::const_iterator split_point( res = node.begin() + 4; break; } - split_key = res->key; + split_key = (*res).key; return res; } diff --git a/src/ftree.h b/src/ftree.h index f71a93a..89406de 100644 --- a/src/ftree.h +++ b/src/ftree.h @@ -14,10 +14,9 @@ #include "tree_nodes_allocator.h" template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key); +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key); static_assert(sizeof(PTreeNode_details) == sizeof(FTreeLeaf_details)); using FTreesBlockArgs = TreeNodesAllocatorArgs; @@ -39,3 +38,4 @@ class FTree : public PTree); diff --git a/src/ftrees.cpp b/src/ftrees.cpp index 376968d..edff82c 100644 --- a/src/ftrees.cpp +++ b/src/ftrees.cpp @@ -7,17 +7,17 @@ #include "ftrees.h" -FTreesConstIterator& FTreesConstIterator::operator++() { +FTreesIterator& FTreesIterator::operator++() { assert(!is_end()); if (is_forward_) { ++ftrees_[index_].iterator; } else { // Switch direction - key_type key = (*this)->key; + key_type key = (**this).key; reverse_end_.reset(index_); // todo: enumrate for (auto& ftree : ftrees_) { - while (!reverse_end_.test(ftree.node->index()) && !ftree.iterator.is_end() && (++ftree.iterator)->key < key) { + while (!reverse_end_.test(ftree.node->index()) && !ftree.iterator.is_end() && (*++ftree.iterator).key < key) { } } is_forward_ = true; @@ -27,7 +27,7 @@ FTreesConstIterator& FTreesConstIterator::operator++() { return *this; } -FTreesConstIterator& FTreesConstIterator::operator--() { +FTreesIterator& FTreesIterator::operator--() { assert(!is_begin()); if (!is_forward_) { if (!reverse_end_.test(index_)) { @@ -35,14 +35,14 @@ FTreesConstIterator& FTreesConstIterator::operator--() { } } else { // Switch direction - key_type key = is_end() ? std::numeric_limits::max() : (*this)->key; + key_type key = is_end() ? std::numeric_limits::max() : (**this).key; for (auto& ftree : ftrees_) { if (ftree.iterator.is_begin()) { - if (ftree.iterator.is_end() || ftree.iterator->key >= key) { + if (ftree.iterator.is_end() || (*ftree.iterator).key >= key) { reverse_end_.set(ftree.node->index()); } } else { - while (!ftree.iterator.is_begin() && (--ftree.iterator)->key > key) { + while (!ftree.iterator.is_begin() && (*--ftree.iterator).key > key) { } } } @@ -55,19 +55,19 @@ FTreesConstIterator& FTreesConstIterator::operator--() { return *this; } -FTreesConstIterator FTreesConstIterator::operator++(int) { - FTreesConstIterator tmp(*this); +FTreesIterator FTreesIterator::operator++(int) { + FTreesIterator tmp(*this); ++(*this); return tmp; } -FTreesConstIterator FTreesConstIterator::operator--(int) { - FTreesConstIterator tmp(*this); +FTreesIterator FTreesIterator::operator--(int) { + FTreesIterator tmp(*this); --(*this); return tmp; } -bool FTreesConstIterator::is_begin() const { +bool FTreesIterator::is_begin() const { if (is_forward_) { return std::ranges::all_of(ftrees_, [](const ftree_info& ftree) { return ftree.iterator.is_begin(); }); } else { @@ -75,37 +75,15 @@ bool FTreesConstIterator::is_begin() const { } } -FTreesIterator& FTreesIterator::operator++() { - FTreesConstIterator::operator++(); - return *this; -} - -FTreesIterator& FTreesIterator::operator--() { - FTreesConstIterator::operator--(); - return *this; -} - -FTreesIterator FTreesIterator::operator++(int) { - FTreesIterator tmp(*this); - ++(*this); - return tmp; -} - -FTreesIterator FTreesIterator::operator--(int) { - FTreesIterator tmp(*this); - --(*this); - return tmp; -} - void FTrees::split(FTrees& left, FTrees& right, key_type& split_point_key) { // Find the ftree with most items auto max_ftree_it = std::ranges::max_element(ftrees_, [](const FTree& a, const FTree& b) { return a.header()->items_count.value() < b.header()->items_count.value(); }); - split_point_key = max_ftree_it->middle()->key; + split_point_key = (*max_ftree_it->middle()).key; for (auto [old_ftree, left_ftree, right_ftree] : std::views::zip(ftrees_, left.ftrees_, right.ftrees_)) { auto pos = old_ftree.find(split_point_key, false); - if (!pos.is_end() && pos->key < split_point_key) + if (!pos.is_end() && (*pos).key < split_point_key) ++pos; old_ftree.split_compact(left_ftree, right_ftree, pos); } @@ -115,7 +93,7 @@ void FTrees::Init() { ftrees_[0].Init(); } -FTrees::iterator FTrees::begin_impl() const { +FTrees::iterator FTrees::begin() const { std::array ftrees_info; std::transform(ftrees_.begin(), ftrees_.end(), ftrees_info.begin(), [](const FTree& cftree) -> typename iterator::ftree_info { @@ -127,7 +105,7 @@ FTrees::iterator FTrees::begin_impl() const { return {std::move(ftrees_info), index}; } -FTrees::iterator FTrees::end_impl() const { +FTrees::iterator FTrees::end() const { std::array ftrees_info; std::transform(ftrees_.begin(), ftrees_.end(), ftrees_info.begin(), [](const FTree& cftree) -> typename iterator::ftree_info { @@ -137,7 +115,7 @@ FTrees::iterator FTrees::end_impl() const { return {std::move(ftrees_info), 0}; } -FTrees::iterator FTrees::find_impl(key_type key, bool exact_match) const { +FTrees::iterator FTrees::find(key_type key, bool exact_match) const { std::array ftrees_info; std::transform(ftrees_.begin(), ftrees_.end(), ftrees_info.begin(), [key](const FTree& cftree) -> typename iterator::ftree_info { @@ -146,12 +124,12 @@ FTrees::iterator FTrees::find_impl(key_type key, bool exact_match) const { }); size_t index = 0; if (exact_match && !std::ranges::any_of(ftrees_info, [key](const iterator::ftree_info& ftree) { - return !ftree.iterator.is_end() && ftree.iterator->key == key; + return !ftree.iterator.is_end() && (*ftree.iterator).key == key; })) { - return end_impl(); + return end(); } auto before_keys = ftrees_info | std::views::filter([key](const iterator::ftree_info& ftree) { - return !ftree.iterator.is_end() && ftree.iterator->key <= key; + return !ftree.iterator.is_end() && (*ftree.iterator).key <= key; }); if (!std::ranges::empty(before_keys)) { // take max key before or key @@ -163,7 +141,7 @@ FTrees::iterator FTrees::find_impl(key_type key, bool exact_match) const { } } else { auto after_keys = ftrees_info | std::views::filter([key](const iterator::ftree_info& ftree) { - return !ftree.iterator.is_end() && ftree.iterator->key > key; + return !ftree.iterator.is_end() && (*ftree.iterator).key > key; }); if (!std::ranges::empty(after_keys)) { index = iterator::find_next_extent_index(after_keys, /*max=*/false); diff --git a/src/ftrees.h b/src/ftrees.h index 0358022..a76eeaa 100644 --- a/src/ftrees.h +++ b/src/ftrees.h @@ -22,6 +22,7 @@ struct free_blocks_extent_ref { union { + node_item_ref_base _base; node_key_ref key; node_value_ref value; const extra_info_ref bucket_index; @@ -36,14 +37,11 @@ struct free_blocks_extent_ref { operator FreeBlocksExtentInfo() const { return {block_number(), blocks_count(), bucket_index}; } bool operator==(const free_blocks_extent_ref& other) const { - uint32_t _key = key; - std::ignore = _key; return key == other.key && value == other.value && bucket_index == other.bucket_index; } }; -static_assert(sizeof(free_blocks_extent_ref) == sizeof(node_item_ref)); -class FTreesConstIterator { +class FTreesIterator { public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; @@ -51,28 +49,23 @@ class FTreesConstIterator { using value_type = free_blocks_extent_ref; using ref_type = free_blocks_extent_ref; - using const_reference = const ref_type; - using const_pointer = const ref_type*; - - using reference = const_reference; - using pointer = const_pointer; + using reference = ref_type; using ftree_info = node_iterator_info; - FTreesConstIterator() = default; - FTreesConstIterator(std::array ftrees, size_t index) + FTreesIterator() = default; + FTreesIterator(std::array ftrees, size_t index) : ftrees_(std::move(ftrees)), index_(index) {} - reference operator*() const { return *operator->(); } - pointer operator->() const& { return reinterpret_cast(ftrees_[index_].iterator.operator->()); } + reference operator*() const { return {(*ftrees_[index_].iterator)._base}; } - FTreesConstIterator& operator++(); - FTreesConstIterator& operator--(); + FTreesIterator& operator++(); + FTreesIterator& operator--(); - FTreesConstIterator operator++(int); - FTreesConstIterator operator--(int); + FTreesIterator operator++(int); + FTreesIterator operator--(int); - bool operator==(const FTreesConstIterator& other) const { + bool operator==(const FTreesIterator& other) const { return index_ == other.index_ && ftrees_[index_].iterator == other.ftrees_[other.index_].iterator; } @@ -85,7 +78,7 @@ class FTreesConstIterator { return !ftree.iterator.is_end() && !reverse_end.test(ftree.node->index()); }); auto res = std::ranges::max_element(iterated_ftrees, [max](const ftree_info& a, const ftree_info& b) { - return max ^ (a.iterator->key > b.iterator->key); + return max ^ ((*a.iterator).key > (*b.iterator).key); }); return res != std::ranges::end(iterated_ftrees) ? res->node->index() : 0; } @@ -100,42 +93,11 @@ class FTreesConstIterator { bool is_forward_{true}; std::bitset reverse_end_; }; - -class FTreesIterator : public FTreesConstIterator { - public: - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = int; - - using ref_type = FTreesConstIterator::ref_type; - - using reference = ref_type; - using pointer = ref_type*; - - FTreesIterator() = default; - FTreesIterator(std::array ftrees, size_t index) - : FTreesConstIterator(std::move(ftrees), index) {} - - reference operator*() const { return *operator->(); } - pointer operator->() const& { return const_cast(FTreesConstIterator::operator->()); } - - FTreesIterator& operator++(); - FTreesIterator& operator--(); - - FTreesIterator operator++(int); - FTreesIterator operator--(int); - - bool operator==(const FTreesIterator& other) const { return FTreesConstIterator::operator==(other); } -}; - -static_assert(std::bidirectional_iterator); static_assert(std::bidirectional_iterator); class FTrees { public: using iterator = FTreesIterator; - using const_iterator = FTreesConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; FTrees(std::shared_ptr block) : ftrees_(CreateFTreeArray(std::move(block), std::make_index_sequence{})) {} @@ -147,21 +109,10 @@ class FTrees { bool empty() const { return size() == 0; } - iterator begin() { return begin_impl(); } - iterator end() { return end_impl(); } - const_iterator begin() const { return begin_impl(); } - const_iterator end() const { return end_impl(); } + iterator begin() const; + iterator end() const; - reverse_iterator rbegin() { return reverse_iterator{end()}; } - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } - - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - iterator find(key_type key, bool exact_match = true) { return find_impl(key, exact_match); } - const_iterator find(key_type key, bool exact_match = true) const { return find_impl(key, exact_match); } + iterator find(key_type key, bool exact_match = true) const; void split(FTrees& left, FTrees& right, key_type& split_point_key); @@ -176,9 +127,6 @@ class FTrees { return {{{block, Is}...}}; } - iterator begin_impl() const; - iterator end_impl() const; - iterator find_impl(key_type key, bool exact_match = true) const; - std::array ftrees_; }; +static_assert(std::ranges::bidirectional_range); diff --git a/src/ptree.cpp b/src/ptree.cpp index 306cab1..6e899f6 100644 --- a/src/ptree.cpp +++ b/src/ptree.cpp @@ -8,10 +8,9 @@ #include "ptree.h" template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key) { +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key) { assert(node.begin() <= pos && pos <= node.end()); assert(node.full()); auto res = pos; @@ -28,6 +27,6 @@ PTreeNode::const_iterator split_point( res = node.begin() + 4; break; } - split_key = res->key; + split_key = (*res).key; return res; } diff --git a/src/ptree.h b/src/ptree.h index 84bad88..5d5ad3c 100644 --- a/src/ptree.h +++ b/src/ptree.h @@ -21,15 +21,14 @@ class Block; template -PTreeNode::const_iterator split_point(const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key); +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key); template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key); +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key); class NodeRefCreator { public: @@ -37,32 +36,25 @@ class NodeRefCreator { }; template -class PTreeConstIterator { +class PTreeIterator { public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; using value_type = typename PTreeNodeIterator::value_type; using ref_type = typename PTreeNodeIterator::ref_type; - using const_reference = typename PTreeNodeConstIterator::const_reference; - using const_pointer = typename PTreeNodeConstIterator::const_pointer; - - using reference = const_reference; - using pointer = const_pointer; + using reference = typename PTreeNodeIterator::reference; using parent_node_info = node_iterator_info>; using leaf_node_info = node_iterator_info>; - PTreeConstIterator() = default; - PTreeConstIterator(const NodeRefCreator* ptree, - std::vector parents, - std::optional leaf) + PTreeIterator() = default; + PTreeIterator(const NodeRefCreator* ptree, std::vector parents, std::optional leaf) : ptree_(ptree), parents_(std::move(parents)), leaf_(std::move(leaf)) {} reference operator*() const { return *leaf_->iterator; } - pointer operator->() const& { return leaf_->iterator.operator->(); } - PTreeConstIterator& operator++() { + PTreeIterator& operator++() { assert(!is_end()); if ((++leaf_->iterator).is_end()) { if (parents_.empty()) @@ -76,12 +68,12 @@ class PTreeConstIterator { return *this; // end } } - uint16_t node_offset = rparent->iterator->value; + uint16_t node_offset = (*rparent->iterator).value; for (auto parent = rparent.base(); parent != parents_.end(); ++parent) { parent_node_info new_parent{{ptree_->get_node_ref(node_offset)}}; new_parent.iterator = new_parent.node->begin(); *parent = std::move(new_parent); - node_offset = parent->iterator->value; + node_offset = (*parent->iterator).value; } leaf_node_info new_leaf{{ptree_->get_node_ref(node_offset)}}; new_leaf.iterator = new_leaf.node->begin(); @@ -90,7 +82,7 @@ class PTreeConstIterator { return *this; } - PTreeConstIterator& operator--() { + PTreeIterator& operator--() { assert(!is_begin()); if (leaf_->iterator.is_begin()) { if (parents_.empty()) @@ -100,13 +92,13 @@ class PTreeConstIterator { if (++rparent == parents_.rend()) return *this; // begin } - uint16_t node_offset = (--rparent->iterator)->value; + uint16_t node_offset = (*--rparent->iterator).value; for (auto parent = rparent.base(); parent != parents_.end(); ++parent) { parent_node_info new_parent{{ptree_->get_node_ref(node_offset)}}; new_parent.iterator = new_parent.node->end(); --new_parent.iterator; *parent = std::move(new_parent); - node_offset = parent->iterator->value; + node_offset = (*parent->iterator).value; } leaf_node_info new_leaf{{ptree_->get_node_ref(node_offset)}}; new_leaf.iterator = new_leaf.node->end(); @@ -116,19 +108,19 @@ class PTreeConstIterator { return *this; } - PTreeConstIterator operator++(int) { - PTreeConstIterator tmp(*this); + PTreeIterator operator++(int) { + PTreeIterator tmp(*this); ++(*this); return tmp; } - PTreeConstIterator operator--(int) { - PTreeConstIterator tmp(*this); + PTreeIterator operator--(int) { + PTreeIterator tmp(*this); --(*this); return tmp; } - bool operator==(const PTreeConstIterator& other) const { + bool operator==(const PTreeIterator& other) const { if (!leaf_ || !other.leaf_) return !leaf_ && !other.leaf_; // to do need to check that belongs to same PTRee return leaf_->iterator == other.leaf_->iterator; @@ -151,68 +143,18 @@ class PTreeConstIterator { std::optional leaf_; }; -template -class PTreeIterator : public PTreeConstIterator { - public: - using base = PTreeConstIterator; - - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = int; - using value_type = base::value_type; - using ref_type = base::ref_type; - - using reference = ref_type; - using pointer = ref_type*; - - using parent_node_info = base::parent_node_info; - using leaf_node_info = base::leaf_node_info; - - PTreeIterator() = default; - PTreeIterator(const NodeRefCreator* ptree, std::vector parents, std::optional leaf) - : base(ptree, std::move(parents), std::move(leaf)) {} - - reference operator*() const { return *base::leaf().iterator; } - pointer operator->() const& { return base::leaf().iterator.operator->(); } - - PTreeIterator& operator++() { - base::operator++(); - return *this; - } - - PTreeIterator& operator--() { - base::operator--(); - return *this; - } - - PTreeIterator operator++(int) { - PTreeIterator tmp(*this); - ++(*this); - return tmp; - } - - PTreeIterator operator--(int) { - PTreeIterator tmp(*this); - --(*this); - return tmp; - } - - bool operator==(const PTreeIterator& other) const { return base::operator==(other); } -}; - template class PTree : public TreeNodesAllocator, public NodeRefCreator { public: using iterator = PTreeIterator; - using const_iterator = PTreeConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; - static_assert(std::bidirectional_iterator); - static_assert(std::bidirectional_iterator); using parent_node = PTreeNode; using leaf_node = PTreeNode; + static_assert(std::ranges::bidirectional_range); + static_assert(std::ranges::bidirectional_range); + PTree(std::shared_ptr block) : TreeNodesAllocator(std::move(block)) {} virtual ~PTree() = default; @@ -225,31 +167,64 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { size_t size() const { return header()->items_count.value(); } bool empty() const { return size() == 0; } - iterator begin() { return begin_impl(); } - iterator end() { return end_impl(); } - const_iterator begin() const { return begin_impl(); } - const_iterator end() const { return end_impl(); } + iterator begin() const { + if (size() == 0) + return {this, {}, std::nullopt}; + std::vector parents; + uint16_t node_offset = header()->root_offset.value(); + for (int i = 0; i < header()->tree_depth.value(); ++i) { + typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; + parent.iterator = parent.node->begin(); + parents.push_back(std::move(parent)); + node_offset = (*parents.back().iterator).value; + } + typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; + leaf.iterator = leaf.node->begin(); + return {this, std::move(parents), std::move(leaf)}; + } - reverse_iterator rbegin() { return reverse_iterator{end()}; } - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } + iterator end() const { + if (size() == 0) + return {this, {}, std::nullopt}; + std::vector parents; + uint16_t node_offset = header()->root_offset.value(); + for (int i = 0; i < header()->tree_depth.value(); ++i) { + typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; + parent.iterator = parent.node->end(); + --parent.iterator; + parents.push_back(std::move(parent)); + node_offset = (*parents.back().iterator).value; + } + typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; + leaf.iterator = leaf.node->end(); + return {this, std::move(parents), std::move(leaf)}; + } - const_iterator middle() const { + iterator middle() const { auto it = begin(); - for ([[maybe_unused]] auto _ : std::views::iota(0, header()->items_count.value() / 2)) { + for ([[maybe_unused]] auto _ : std::views::iota(size_t{0}, size() / 2)) { ++it; } return it; } + iterator find(key_type key, bool exact_match = true) const { + if (size() == 0) + return {this, {}, std::nullopt}; // TODO empty tree iterator constructor + std::vector parents; + uint16_t node_offset = header()->root_offset.value(); + for (int i = 0; i < header()->tree_depth.value(); ++i) { + typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; + parent.iterator = parent.node->find(key, false); + assert(!parent.iterator.is_end()); + parents.push_back(std::move(parent)); + node_offset = (*parents.back().iterator).value; + } + typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; + leaf.iterator = leaf.node->find(key, exact_match); + return {this, std::move(parents), std::move(leaf)}; + } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - iterator find(key_type key, bool exact_match = true) { return find_impl(key, exact_match); } - const_iterator find(key_type key, bool exact_match = true) const { return find_impl(key, exact_match); } - - LeafNodeDetails* grow_tree(const const_iterator& pos, key_type split_key) { + LeafNodeDetails* grow_tree(const iterator& pos, key_type split_key) { uint16_t nodes_to_alloc = 1; auto parent = pos.parents().rbegin(); while (parent != pos.parents().rend() && parent->node->full()) { @@ -280,7 +255,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { // We need to insert it first or we will loose the the key. (since we don't store the key for [0]) new_node.insert(new_node.begin(), {child_split_key, child_node_offset}); } - new_node.insert(new_node.end(), parent_split_pos, parent->node->cend()); + new_node.insert(new_node.end(), parent_split_pos, parent->node->end()); parent->node->erase(parent_split_pos, parent->node->end()); if (child_split_key > split_key) { new_node.insert(new_node.begin() + ((parent->iterator - parent_split_pos) + 1), @@ -309,14 +284,14 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { bool insert(const typename iterator::value_type& key_val) { auto pos = find(key_val.key, false); - if (!pos.is_end() && pos->key == key_val.key) { + if (!pos.is_end() && (*pos).key == key_val.key) { // key already exists return false; } return insert(pos, key_val); } - bool insert(const const_iterator& pos, const typename iterator::value_type& key_val) { + bool insert(const iterator& pos, const typename iterator::value_type& key_val) { auto items_count = header()->items_count.value(); if (items_count == 0) { // first item in tree @@ -335,7 +310,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { header->tree_depth = 0; return true; } - auto leaf_pos_to_insert = key_val.key < pos->key ? pos.leaf().iterator : pos.leaf().iterator + 1; + auto leaf_pos_to_insert = key_val.key < (*pos).key ? pos.leaf().iterator : pos.leaf().iterator + 1; if (!pos.leaf().node->full()) { // We have place to add the new key/val pos.leaf().node->insert(leaf_pos_to_insert, key_val); @@ -349,7 +324,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { return false; leaf_node new_node{get_node_ref(this->to_offset(node)), 0}; new_node.clear(true); - new_node.insert(new_node.begin(), split_pos, pos.leaf().node->cend()); + new_node.insert(new_node.begin(), split_pos, pos.leaf().node->end()); pos.leaf().node->erase(split_pos, pos.leaf().node->end()); if (key_val.key >= split_key) { new_node.insert(new_node.begin() + (leaf_pos_to_insert - split_pos), key_val); @@ -360,7 +335,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { return true; } - bool insert(const const_iterator& it_start, const const_iterator& it_end) { + bool insert(const iterator& it_start, const iterator& it_end) { for (const auto& val : std::ranges::subrange(it_start, it_end)) { if (!insert(val)) return false; @@ -368,7 +343,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { return true; } - bool insert_compact(const const_iterator& it_start, const const_iterator& it_end) { + bool insert_compact(const iterator& it_start, const iterator& it_end) { if (!empty()) { assert(false); return false; @@ -388,7 +363,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { } new_node.insert(new_node.begin(), range_start, it); header->items_count += static_cast(new_node.size()); - current_nodes.push_back({new_node.begin()->key, this->to_offset(node)}); + current_nodes.push_back({(*new_node.begin()).key, this->to_offset(node)}); } // Create the tree @@ -415,7 +390,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { return true; } - void erase(const const_iterator& pos) { + void erase(const iterator& pos) { pos.leaf().node->erase(pos.leaf().iterator); if (pos.leaf().node->empty()) { this->Free(pos.leaf().node->node(), 1); @@ -442,7 +417,7 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { ; } - void erase(const const_iterator& it_start, const const_iterator& it_end) { + void erase(const iterator& it_start, const iterator& it_end) { // Iterating from last to first is safe as the iterator will always be valid after operator--. It isn't true in the // other direction. auto it = it_end; @@ -451,70 +426,19 @@ class PTree : public TreeNodesAllocator, public NodeRefCreator { } } - void split(PTree& left, PTree& right, const const_iterator& pos) const { + void split(PTree& left, PTree& right, const iterator& pos) const { left.insert(begin(), pos); right.insert(pos, end()); } - void split(PTree& right, const_iterator& pos) { + void split(PTree& right, iterator& pos) { auto end_pos = end(); right.insert(pos, end_pos); erase(pos, end_pos); } - void split_compact(PTree& left, PTree& right, const const_iterator& pos) const { + void split_compact(PTree& left, PTree& right, const iterator& pos) const { left.insert_compact(begin(), pos); right.insert_compact(pos, end()); } - - private: - iterator begin_impl() const { - if (size() == 0) - return {this, {}, std::nullopt}; - std::vector parents; - uint16_t node_offset = header()->root_offset.value(); - for (int i = 0; i < header()->tree_depth.value(); ++i) { - typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; - parent.iterator = parent.node->begin(); - parents.push_back(std::move(parent)); - node_offset = parents.back().iterator->value; - } - typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; - leaf.iterator = leaf.node->begin(); - return {this, std::move(parents), std::move(leaf)}; - } - - iterator end_impl() const { - if (size() == 0) - return {this, {}, std::nullopt}; - std::vector parents; - uint16_t node_offset = header()->root_offset.value(); - for (int i = 0; i < header()->tree_depth.value(); ++i) { - typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; - parent.iterator = parent.node->end(); - --parent.iterator; - parents.push_back(std::move(parent)); - node_offset = parents.back().iterator->value; - } - typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; - leaf.iterator = leaf.node->end(); - return {this, std::move(parents), std::move(leaf)}; - } - - iterator find_impl(key_type key, bool exact_match = true) const { - if (size() == 0) - return {this, {}, std::nullopt}; // TODO empty tree iterator constructor - std::vector parents; - uint16_t node_offset = header()->root_offset.value(); - for (int i = 0; i < header()->tree_depth.value(); ++i) { - typename iterator::parent_node_info parent{{get_node_ref(node_offset)}}; - parent.iterator = parent.node->find(key, false); - assert(!parent.iterator.is_end()); - parents.push_back(std::move(parent)); - node_offset = parents.back().iterator->value; - } - typename iterator::leaf_node_info leaf{{get_node_ref(node_offset)}}; - leaf.iterator = leaf.node->find(key, exact_match); - return {this, std::move(parents), std::move(leaf)}; - } }; diff --git a/src/ptree_node.h b/src/ptree_node.h index fb96d8d..1a0b89c 100644 --- a/src/ptree_node.h +++ b/src/ptree_node.h @@ -123,14 +123,11 @@ struct node_item { template struct node_item_ref { union { + node_item_ref_base _base; node_key_ref key; node_value_ref value; }; - node_item_ref() = default; - node_item_ref(const node_item_ref& other) = default; - node_item_ref(node_item_ref&& other) = default; - node_item_ref& operator=(const node_item_ref& other) { key = other.key; value = other.value; @@ -161,154 +158,82 @@ struct node_item_ref { }; template -auto operator<=>(key_type key, const node_item& node_value) { - return key <=> node_value; -} -template -auto operator==(key_type key, const node_item& node_value) { - return key == node_value; -} - -template -concept TreeIterator = requires(const T& iterator) { - { iterator.is_begin() } -> std::same_as; - { iterator.is_end() } -> std::same_as; - }; - -template - requires TreeIterator -class TreeReverseIterator : public std::reverse_iterator { - public: - TreeReverseIterator() = default; - explicit TreeReverseIterator(T it) : std::reverse_iterator(std::move(it)) {} - TreeReverseIterator(const TreeReverseIterator& other) : std::reverse_iterator(other) {} - TreeReverseIterator(TreeReverseIterator&& other) : std::reverse_iterator(other) {} - template - requires std::convertible_to - TreeReverseIterator(const TreeReverseIterator& it) : std::reverse_iterator(std::move(it)) {} - - typename T::pointer operator->() const& { - T tmp(std::reverse_iterator::base()); - --tmp; - // We need to store the value for the ref. - const_cast(this)->val_ = *reinterpret_cast(tmp.operator->()); - return reinterpret_cast(const_cast(&val_)); - } - - TreeReverseIterator& operator++() { - std::reverse_iterator::operator++(); - return *this; - } - TreeReverseIterator& operator--() { - std::reverse_iterator::operator--(); - return *this; - } - TreeReverseIterator operator++(int) { - TreeReverseIterator tmp(*this); - ++(*this); - return tmp; - } - TreeReverseIterator operator--(int) { - TreeReverseIterator tmp(*this); - --(*this); - return tmp; - } - TreeReverseIterator& operator=(const TreeReverseIterator& other) { - std::reverse_iterator::operator=(other); - return *this; - } - - bool is_begin() const { return this->base().is_end(); } - bool is_end() const { return this->base().is_begin(); } - - private: - node_item_ref_base val_; - static_assert(sizeof(typename std::remove_pointer_t) == sizeof(val_)); -}; - -template -class PTreeNodeConstIterator { +class PTreeNodeIterator { public: using iterator_category = std::random_access_iterator_tag; using difference_type = int; using value_type = node_item; using ref_type = node_item_ref; - static_assert(sizeof(ref_type) == sizeof(node_item_ref_base)); - using const_reference = const ref_type; - using const_pointer = const ref_type*; - - using reference = const_reference; - using pointer = const_pointer; + using reference = ref_type; - PTreeNodeConstIterator() = default; - PTreeNodeConstIterator(node_ref node, size_t index) : PTreeNodeConstIterator(node_item_ref_base{node, index}) {} - PTreeNodeConstIterator(node_item_ref_base node_item) : node_item_(node_item) { + PTreeNodeIterator() = default; + PTreeNodeIterator(node_ref node, size_t index) : PTreeNodeIterator(node_item_ref_base{node, index}) {} + PTreeNodeIterator(node_item_ref_base node_item) : node_item_(node_item) { assert(node_item_.index <= node_values_capacity::value); } - reference operator*() const { return *operator->(); } - pointer operator->() const& { return reinterpret_cast(&node_item_); } + reference operator*() const { return {node_item_}; } - PTreeNodeConstIterator& operator++() { + PTreeNodeIterator& operator++() { ++node_item_.index; return *this; } - PTreeNodeConstIterator& operator--() { + PTreeNodeIterator& operator--() { --node_item_.index; return *this; } - PTreeNodeConstIterator operator++(int) { - PTreeNodeConstIterator tmp(*this); + PTreeNodeIterator operator++(int) { + PTreeNodeIterator tmp(*this); ++(*this); return tmp; } - PTreeNodeConstIterator operator--(int) { - PTreeNodeConstIterator tmp(*this); + PTreeNodeIterator operator--(int) { + PTreeNodeIterator tmp(*this); --(*this); return tmp; } - PTreeNodeConstIterator& operator+=(difference_type n) { + PTreeNodeIterator& operator+=(difference_type n) { node_item_.index += n; assert(node_item_.index <= node_values_capacity::value); return *this; } - PTreeNodeConstIterator& operator-=(difference_type n) { + PTreeNodeIterator& operator-=(difference_type n) { node_item_.index -= n; assert(node_item_.index <= node_values_capacity::value); return *this; } - PTreeNodeConstIterator operator+(difference_type n) const { - PTreeNodeConstIterator tmp(*this); + PTreeNodeIterator operator+(difference_type n) const { + PTreeNodeIterator tmp(*this); tmp += n; return tmp; } - PTreeNodeConstIterator operator-(difference_type n) const { - PTreeNodeConstIterator tmp(*this); + PTreeNodeIterator operator-(difference_type n) const { + PTreeNodeIterator tmp(*this); tmp -= n; return tmp; } - difference_type operator-(const PTreeNodeConstIterator& other) const { + difference_type operator-(const PTreeNodeIterator& other) const { assert(node_item_.get() == other.node_item_.template get()); return static_cast(node_item_.index) - static_cast(other.node_item_.index); } - auto operator<=>(const PTreeNodeConstIterator& other) const { + auto operator<=>(const PTreeNodeIterator& other) const { if (const auto res = node_item_.get() <=> other.node_item_.template get(); res != 0) return res; return node_item_.index <=> other.node_item_.index; } - bool operator==(const PTreeNodeConstIterator& other) const { return node_item_ == other.node_item_; } + bool operator==(const PTreeNodeIterator& other) const { return node_item_ == other.node_item_; } - const ref_type operator[](difference_type n) const { return *(*this + n); } + reference operator[](difference_type n) const { return *(*this + n); } bool is_begin() const { return node_item_.index == 0; } bool is_end() const { @@ -320,116 +245,25 @@ class PTreeNodeConstIterator { node_item_ref_base node_item_; }; -template -class PTreeNodeIterator : public PTreeNodeConstIterator { - public: - using base = PTreeNodeConstIterator; - - using iterator_category = std::random_access_iterator_tag; - using difference_type = int; - using value_type = node_item; - - using ref_type = node_item_ref; - - using reference = ref_type; - using pointer = ref_type*; - - PTreeNodeIterator() = default; - PTreeNodeIterator(node_ref node, size_t index) : base(node, index) {} - PTreeNodeIterator(node_item_ref_base node_item) : base(node_item) {} - - reference operator*() const { return *operator->(); } - pointer operator->() const& { return const_cast(base::operator->()); } - - PTreeNodeIterator& operator++() { - base::operator++(); - return *this; - } - - PTreeNodeIterator& operator--() { - base::operator--(); - return *this; - } - - PTreeNodeIterator operator++(int) { - PTreeNodeIterator tmp(*this); - ++(*this); - return tmp; - } - PTreeNodeIterator operator--(int) { - PTreeNodeIterator tmp(*this); - --(*this); - return tmp; - } - - PTreeNodeIterator& operator+=(difference_type n) { - base::operator+=(n); - return *this; - } - PTreeNodeIterator& operator-=(difference_type n) { - base::operator-=(n); - return *this; - } - PTreeNodeIterator operator+(difference_type n) const { - PTreeNodeIterator tmp(*this); - tmp += n; - return tmp; - ; - } - PTreeNodeIterator operator-(difference_type n) const { - PTreeNodeIterator tmp(*this); - tmp -= n; - return tmp; - } - difference_type operator-(const PTreeNodeIterator& other) const { return base::operator-(other); } - difference_type operator-(const PTreeNodeConstIterator& other) const { return base::operator-(other); } - - reference operator[](difference_type n) const { return const_cast(base::operator[](n)); } -}; - -template -PTreeNodeConstIterator operator+(typename PTreeNodeConstIterator::difference_type n, - const PTreeNodeConstIterator& iter) { - return iter + n; -} - template PTreeNodeIterator operator+(typename PTreeNodeIterator::difference_type n, const PTreeNodeIterator& iter) { return iter + n; } template -PTreeNodeConstIterator::difference_type operator-(const PTreeNodeConstIterator& a, - const PTreeNodeIterator& b) { - return a.operator-(b); -} - -template - requires std::random_access_iterator> && std::random_access_iterator> class PTreeNode { public: using iterator = PTreeNodeIterator; - using const_iterator = PTreeNodeConstIterator; - using reverse_iterator = TreeReverseIterator; - using const_reverse_iterator = TreeReverseIterator; + static_assert(std::random_access_iterator); + + using reference = typename iterator::reference; PTreeNode(node_ref node) : PTreeNode(node, node_values_size(*node.get())) {} PTreeNode(node_ref node, size_t size) : node_(node), size_(size) {} size_t size() const { return size_; } - iterator begin() { return iterator(node_, 0); } - iterator end() { return iterator(node_, size_); } - const_iterator begin() const { return const_iterator(node_, 0); } - const_iterator end() const { return const_iterator(node_, size_); } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - reverse_iterator rbegin() { return {end()}; } - reverse_iterator rend() { return {begin()}; } - const_reverse_iterator rbegin() const { return {end()}; } - const_reverse_iterator rend() const { return {begin()}; } - const_reverse_iterator crbegin() const { return rbegin(); } - const_reverse_iterator crend() const { return rend(); } + iterator begin() const { return iterator(node_, 0); } + iterator end() const { return iterator(node_, size_); } bool full() const { return size_ == node_values_capacity::value; } bool empty() const { return size_ == 0; } @@ -438,57 +272,57 @@ class PTreeNode { auto it = std::upper_bound(begin(), end(), key); if (it != begin()) --it; - if (exact_match && (it == end() || it->key != key)) + if (exact_match && (it == end() || (*it).key != key)) return end(); return it; } - iterator insert(const const_iterator& pos, const typename iterator::value_type& key_val) { + iterator insert(const iterator& pos, const typename iterator::value_type& key_val) { if (size_ >= node_values_capacity::value) return end(); - assert(cbegin() <= pos && pos <= cend()); - iterator res = begin() + (pos - cbegin()); - std::copy_backward(res, cend(), end() + 1); + assert(begin() <= pos && pos <= end()); + iterator res = begin() + (pos - begin()); + std::copy_backward(res, end(), end() + 1); *res = key_val; size_++; return res; } template - iterator insert(const const_iterator& pos, Range&& range) { + iterator insert(const iterator& pos, Range&& range) { return insert(pos, std::ranges::begin(range), std::ranges::end(range)); } template - iterator insert(const const_iterator& pos, const InputIt& start_it, const InputIt& end_it) { + iterator insert(const iterator& pos, const InputIt& start_it, const InputIt& end_it) { auto items = static_cast(std::distance(start_it, end_it)); if (size_ + items > node_values_capacity::value) return end(); - assert(cbegin() <= pos && pos <= cend()); - iterator res = begin() + (pos - cbegin()); - std::copy_backward(res, cend(), end() + items); + assert(begin() <= pos && pos <= end()); + iterator res = begin() + (pos - begin()); + std::copy_backward(res, end(), end() + items); std::copy(start_it, end_it, res); size_ += items; return res; } - iterator erase(const const_iterator& pos) { - assert(cbegin() <= pos && pos < cend()); + iterator erase(const iterator& pos) { + assert(begin() <= pos && pos < end()); auto new_end = end() - 1; - iterator res = begin() + (pos - cbegin()); - std::copy(pos + 1, cend(), res); + iterator res = begin() + (pos - begin()); + std::copy(pos + 1, end(), res); std::fill(new_end, end(), 0); --size_; return res; } - iterator erase(const const_iterator& it_start, const const_iterator& it_end) { - assert(cbegin() <= it_start && it_start <= cend()); - assert(cbegin() <= it_end && it_end <= cend()); + iterator erase(const iterator& it_start, const iterator& it_end) { + assert(begin() <= it_start && it_start <= end()); + assert(begin() <= it_end && it_end <= end()); assert(it_start <= it_end); - iterator res = begin() + (it_start - cbegin()); - auto new_end = res + (cend() - it_end); - std::copy(it_end, cend(), res); + iterator res = begin() + (it_start - begin()); + auto new_end = res + (end() - it_end); + std::copy(it_end, end(), res); std::fill(new_end, end(), 0); size_ -= it_end - it_start; return res; diff --git a/src/rtree.cpp b/src/rtree.cpp index b1d2fb8..c14eb06 100644 --- a/src/rtree.cpp +++ b/src/rtree.cpp @@ -8,10 +8,9 @@ #include "rtree.h" template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key) { +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key) { assert(node.begin() <= pos && pos <= node.end()); assert(node.full()); auto res = pos; @@ -29,7 +28,7 @@ PTreeNode::const_iterator split_point( res = node.begin() + 3; break; } - split_key = res->key; + split_key = (*res).key; return res; } diff --git a/src/rtree.h b/src/rtree.h index 6e7f52d..f8726ef 100644 --- a/src/rtree.h +++ b/src/rtree.h @@ -12,10 +12,9 @@ #include "structs.h" template <> -PTreeNode::const_iterator split_point( - const PTreeNode& node, - const typename PTreeNode::const_iterator& pos, - key_type& split_key); +PTreeNode::iterator split_point(const PTreeNode& node, + const typename PTreeNode::iterator& pos, + key_type& split_key); static_assert(sizeof(PTreeNode_details) == sizeof(RTreeLeaf_details)); using EPTreeBlockArgs = TreeNodesAllocatorArgs; @@ -31,3 +30,4 @@ class RTree : public PTree); diff --git a/tests/eptree_tests.cpp b/tests/eptree_tests.cpp index 55cef1d..8b3eb53 100644 --- a/tests/eptree_tests.cpp +++ b/tests/eptree_tests.cpp @@ -68,7 +68,7 @@ TEST_CASE("EPTreeTests") { }))); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(eptree.find(i, true)->key == i); + REQUIRE((*eptree.find(i, true)).key == i); } } @@ -110,7 +110,7 @@ TEST_CASE("EPTreeTests") { auto it = eptree.begin(); uint32_t steps = 0; while (it != eptree.end()) { - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); ++it; ++steps; } @@ -119,7 +119,7 @@ TEST_CASE("EPTreeTests") { while (it != eptree.begin()) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } REQUIRE(steps == 0); REQUIRE(it.is_begin()); @@ -127,13 +127,13 @@ TEST_CASE("EPTreeTests") { for (int i = 0; i < 40; ++i) { ++it; ++steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 20; ++i) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } - REQUIRE(it->key == 20); + REQUIRE((*it).key == 20); } } diff --git a/tests/free_blocks_tree_bucket_tests.cpp b/tests/free_blocks_tree_bucket_tests.cpp index 7e78542..9134e78 100644 --- a/tests/free_blocks_tree_bucket_tests.cpp +++ b/tests/free_blocks_tree_bucket_tests.cpp @@ -48,7 +48,7 @@ TEST_CASE("FreeBlocksTreeBucketTests") { }))); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(bucket.find(i, true)->key == i); + REQUIRE((*bucket.find(i, true)).key == i); } } @@ -76,7 +76,7 @@ TEST_CASE("FreeBlocksTreeBucketTests") { }))); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(bucket.find(i, true)->key == i); + REQUIRE((*bucket.find(i, true)).key == i); } } @@ -145,8 +145,8 @@ TEST_CASE("FreeBlocksTreeBucketTests") { REQUIRE(ftree2.empty()); REQUIRE(ftree3.empty()); REQUIRE(bucket.find(150, false) != bucket.end()); - REQUIRE(bucket.find(150, false)->key == 50); - REQUIRE(bucket.find(25, false)->key == 50); + REQUIRE((*bucket.find(150, false)).key == 50); + REQUIRE((*bucket.find(25, false)).key == 50); REQUIRE( std::ranges::equal(std::views::transform(bucket, [](const value_type& extent) -> int { return extent.key; }), std::list{50})); @@ -158,8 +158,8 @@ TEST_CASE("FreeBlocksTreeBucketTests") { REQUIRE(ftree1.size() == 1); REQUIRE(ftree2.size() == 1); REQUIRE(ftree3.empty()); - REQUIRE(bucket.find(150, false)->key == 50); - REQUIRE(bucket.find(250, false)->key == 160); + REQUIRE((*bucket.find(150, false)).key == 50); + REQUIRE((*bucket.find(250, false)).key == 160); REQUIRE( std::ranges::equal(std::views::transform(bucket, [](const value_type& extent) -> int { return extent.key; }), std::list{50, 160})); @@ -173,9 +173,9 @@ TEST_CASE("FreeBlocksTreeBucketTests") { REQUIRE(ftree1.empty()); REQUIRE(ftree2.size() == 1); REQUIRE(ftree3.empty()); - REQUIRE(bucket.find(150, false)->key == 160); - REQUIRE(bucket.find(250, false)->key == 160); - REQUIRE(bucket.find(25, false)->key == 160); + REQUIRE((*bucket.find(150, false)).key == 160); + REQUIRE((*bucket.find(250, false)).key == 160); + REQUIRE((*bucket.find(25, false)).key == 160); REQUIRE( std::ranges::equal(std::views::transform(bucket, [](const value_type& extent) -> int { return extent.key; }), std::list{160})); @@ -193,7 +193,7 @@ TEST_CASE("FreeBlocksTreeBucketTests") { auto it = bucket.begin(); uint32_t steps = 0; while (it != bucket.end()) { - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); ++it; ++steps; } @@ -202,7 +202,7 @@ TEST_CASE("FreeBlocksTreeBucketTests") { while (it != bucket.begin()) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } REQUIRE(steps == 0); REQUIRE(it.is_begin()); @@ -210,13 +210,13 @@ TEST_CASE("FreeBlocksTreeBucketTests") { for (int i = 0; i < 40; ++i) { ++it; ++steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 20; ++i) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } - REQUIRE(it->key == 20); + REQUIRE((*it).key == 20); } } diff --git a/tests/free_blocks_tree_tests.cpp b/tests/free_blocks_tree_tests.cpp index 8c08da8..02ccdcd 100644 --- a/tests/free_blocks_tree_tests.cpp +++ b/tests/free_blocks_tree_tests.cpp @@ -49,7 +49,7 @@ TEST_CASE("FreeBlocksTreeTests") { }))); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(tree.find(i)->key == i); + REQUIRE((*tree.find(i)).key == i); } } @@ -77,7 +77,7 @@ TEST_CASE("FreeBlocksTreeTests") { }))); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(tree.find(i)->key == i); + REQUIRE((*tree.find(i)).key == i); } } @@ -147,8 +147,8 @@ TEST_CASE("FreeBlocksTreeTests") { REQUIRE(ftree2.empty()); REQUIRE(ftree3.empty()); REQUIRE(tree.find(150, false) != tree.end()); - REQUIRE(tree.find(150, false)->key == 50); - REQUIRE(tree.find(25, false)->key == 50); + REQUIRE((*tree.find(150, false)).key == 50); + REQUIRE((*tree.find(25, false)).key == 50); REQUIRE(std::ranges::equal(std::views::transform(tree, [](const value_type& extent) -> int { return extent.key; }), std::list{50})); REQUIRE(std::ranges::equal( @@ -159,8 +159,8 @@ TEST_CASE("FreeBlocksTreeTests") { REQUIRE(ftree1.size() == 1); REQUIRE(ftree2.size() == 1); REQUIRE(ftree3.empty()); - REQUIRE(tree.find(150, false)->key == 50); - REQUIRE(tree.find(250, false)->key == 160); + REQUIRE((*tree.find(150, false)).key == 50); + REQUIRE((*tree.find(250, false)).key == 160); REQUIRE(std::ranges::equal(std::views::transform(tree, [](const value_type& extent) -> int { return extent.key; }), std::list{50, 160})); REQUIRE(std::ranges::equal( @@ -173,9 +173,9 @@ TEST_CASE("FreeBlocksTreeTests") { REQUIRE(ftree1.empty()); REQUIRE(ftree2.size() == 1); REQUIRE(ftree3.empty()); - REQUIRE(tree.find(150, false)->key == 160); - REQUIRE(tree.find(250, false)->key == 160); - REQUIRE(tree.find(25, false)->key == 160); + REQUIRE((*tree.find(150, false)).key == 160); + REQUIRE((*tree.find(250, false)).key == 160); + REQUIRE((*tree.find(25, false)).key == 160); REQUIRE(std::ranges::equal(std::views::transform(tree, [](const value_type& extent) -> int { return extent.key; }), std::list{160})); REQUIRE(std::ranges::equal( @@ -192,7 +192,7 @@ TEST_CASE("FreeBlocksTreeTests") { auto it = tree.begin(); uint32_t steps = 0; while (it != tree.end()) { - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); ++it; ++steps; } @@ -201,7 +201,7 @@ TEST_CASE("FreeBlocksTreeTests") { while (it != tree.begin()) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } REQUIRE(steps == 0); REQUIRE(it.is_begin()); @@ -209,13 +209,13 @@ TEST_CASE("FreeBlocksTreeTests") { for (int i = 0; i < 40; ++i) { ++it; ++steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 20; ++i) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } - REQUIRE(it->key == 20); + REQUIRE((*it).key == 20); } } diff --git a/tests/ftree_tests.cpp b/tests/ftree_tests.cpp index ab78ea3..123dc66 100644 --- a/tests/ftree_tests.cpp +++ b/tests/ftree_tests.cpp @@ -96,8 +96,8 @@ TEST_CASE("FTreeTests") { REQUIRE(std::distance(ftree.begin(), ftree.end()) == kItemsCount); REQUIRE(std::ranges::equal(ftrees[0], ftree)); for (uint32_t i = 0; i < kItemsCount; ++i) { - REQUIRE(ftree.find(i)->key == i); - REQUIRE(ftree.find(i)->value == static_cast(i % 16)); + REQUIRE((*ftree.find(i)).key == i); + REQUIRE((*ftree.find(i)).value == static_cast(i % 16)); } } @@ -110,7 +110,7 @@ TEST_CASE("FTreeTests") { auto it = ftrees[0].begin(); uint32_t steps = 0; while (it != ftrees[0].end()) { - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); ++it; ++steps; } @@ -119,7 +119,7 @@ TEST_CASE("FTreeTests") { while (it != ftrees[0].begin()) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } REQUIRE(steps == 0); REQUIRE(it.is_begin()); @@ -127,23 +127,23 @@ TEST_CASE("FTreeTests") { for (int i = 0; i < 4; ++i) { ++it; ++steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 2; ++i) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 40; ++i) { ++it; ++steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } for (int i = 0; i < 20; ++i) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } - REQUIRE(it->key == 22); + REQUIRE((*it).key == 22); } } diff --git a/tests/ftrees_tests.cpp b/tests/ftrees_tests.cpp index f34c868..f7ff359 100644 --- a/tests/ftrees_tests.cpp +++ b/tests/ftrees_tests.cpp @@ -71,7 +71,7 @@ TEST_CASE("FTreesTests") { auto it = ftrees.begin(); uint32_t steps = 0; while (it != ftrees.end()) { - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); ++it; ++steps; } @@ -80,21 +80,22 @@ TEST_CASE("FTreesTests") { while (it != ftrees.begin()) { --it; --steps; - REQUIRE(it->key == steps); + REQUIRE((*it).key == steps); } REQUIRE(steps == 0); REQUIRE(it.is_begin()); for (int i = 0; i < 40; ++i) { - UNSCOPED_INFO(it->key); ++it; + ++steps; + REQUIRE((*it).key == steps); } for (int i = 0; i < 20; ++i) { - UNSCOPED_INFO(it->key); --it; + --steps; + REQUIRE((*it).key == steps); } - UNSCOPED_INFO(it->key); - REQUIRE(it->key == 20); + REQUIRE((*it).key == 20); } SECTION("check find") { @@ -107,7 +108,7 @@ TEST_CASE("FTreesTests") { REQUIRE(it.is_end()); it = ftrees.find(523, false); - REQUIRE(it->key == 522); + REQUIRE((*it).key == 522); REQUIRE(std::ranges::equal( std::views::transform(std::ranges::subrange(ftrees.begin(), it), @@ -128,7 +129,7 @@ TEST_CASE("FTreesTests") { }))); it = ftrees.find(840); - REQUIRE(it->key == 840); + REQUIRE((*it).key == 840); REQUIRE(std::ranges::equal( std::views::transform(std::ranges::subrange(ftrees.begin(), it), @@ -148,10 +149,10 @@ TEST_CASE("FTreesTests") { return {i * 2, static_cast(i % 16), static_cast(i % kSizeBuckets.size())}; }))); - REQUIRE(ftrees.find(4, false)->key == 4); - REQUIRE(ftrees.find(6, false)->key == 6); - REQUIRE((++ftrees.find(4, false))->key == 6); - REQUIRE((++ftrees.find(14, false))->key == 16); + REQUIRE((*ftrees.find(4, false)).key == 4); + REQUIRE((*ftrees.find(6, false)).key == 6); + REQUIRE((*++ftrees.find(4, false)).key == 6); + REQUIRE((*++ftrees.find(14, false)).key == 16); } SECTION("test split") { diff --git a/tests/rtree_tests.cpp b/tests/rtree_tests.cpp index cf04506..3185660 100644 --- a/tests/rtree_tests.cpp +++ b/tests/rtree_tests.cpp @@ -151,7 +151,7 @@ TEST_CASE("RTreeTests") { }))); for (uint32_t i = 0; i < index; ++i) { - REQUIRE(rtree.find(i, true)->key == i); + REQUIRE((*rtree.find(i, true)).key == i); } }