Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Removed
- bazel version requirement file `.bazelversion`. [#89](https://github.com/tzaeschke/phtree-cpp/issues/89)

###
- Fixed copy cstr/assignment of B+trees, see also #102. [#119](https://github.com/tzaeschke/phtree-cpp/pull/119)

## [1.4.0] - 2022-09-09
### Added
- Added build features: [#53](https://github.com/tzaeschke/phtree-cpp/issues/53)
Expand Down
9 changes: 4 additions & 5 deletions include/phtree/common/b_plus_tree_hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ class b_plus_tree_hash_set {
explicit b_plus_tree_hash_set() : root_{new NLeafT(nullptr, nullptr, nullptr)}, size_{0} {};

b_plus_tree_hash_set(const b_plus_tree_hash_set& other) : size_{other.size_} {
root_ = other.root_->is_leaf() ? new NLeafT(*other.root_->as_leaf())
: new NInnerT(*other.root_->as_inner());
root_ = other.root_->is_leaf() ? (NodeT*)new NLeafT(*other.root_->as_leaf())
: (NodeT*)new NInnerT(*other.root_->as_inner());
}

b_plus_tree_hash_set(b_plus_tree_hash_set&& other) noexcept
Expand All @@ -109,8 +109,8 @@ class b_plus_tree_hash_set {
b_plus_tree_hash_set& operator=(const b_plus_tree_hash_set& other) {
assert(this != &other);
delete root_;
root_ = other.root_->is_leaf() ? new NLeafT(*other.root_->as_leaf())
: new NInnerT(*other.root_->as_inner());
root_ = other.root_->is_leaf() ? (NodeT*)new NLeafT(*other.root_->as_leaf())
: (NodeT*)new NInnerT(*other.root_->as_inner());
size_ = other.size_;
return *this;
}
Expand All @@ -126,7 +126,6 @@ class b_plus_tree_hash_set {

~b_plus_tree_hash_set() {
delete root_;
root_ = nullptr;
}

[[nodiscard]] auto find(const T& value) {
Expand Down
9 changes: 4 additions & 5 deletions include/phtree/common/b_plus_tree_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ class b_plus_tree_map {
explicit b_plus_tree_map() : root_{new NLeafT(nullptr, nullptr, nullptr)}, size_{0} {};

b_plus_tree_map(const b_plus_tree_map& other) : size_{other.size_} {
root_ = other.root_->is_leaf() ? new NLeafT(*other.root_->as_leaf())
: new NInnerT(*other.root_->as_inner());
root_ = other.root_->is_leaf() ? (NodeT*)new NLeafT(*other.root_->as_leaf())
: (NodeT*)new NInnerT(*other.root_->as_inner());
}

b_plus_tree_map(b_plus_tree_map&& other) noexcept : root_{other.root_}, size_{other.size_} {
Expand All @@ -112,8 +112,8 @@ class b_plus_tree_map {
b_plus_tree_map& operator=(const b_plus_tree_map& other) {
assert(this != &other);
delete root_;
root_ = other.root_->is_leaf() ? new NLeafT(*other.root_->as_leaf())
: new NInnerT(*other.root_->as_inner());
root_ = other.root_->is_leaf() ? (NodeT*)new NLeafT(*other.root_->as_leaf())
: (NodeT*)new NInnerT(*other.root_->as_inner());
size_ = other.size_;
return *this;
}
Expand All @@ -129,7 +129,6 @@ class b_plus_tree_map {

~b_plus_tree_map() {
delete root_;
root_ = nullptr;
}

[[nodiscard]] auto find(KeyT key) noexcept {
Expand Down
1 change: 0 additions & 1 deletion include/phtree/common/b_plus_tree_multimap.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ class b_plus_tree_multimap {

~b_plus_tree_multimap() {
delete root_;
root_ = nullptr;
}

[[nodiscard]] auto find(const KeyT key) {
Expand Down
87 changes: 87 additions & 0 deletions test/common/b_plus_tree_hash_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,90 @@ TEST(PhTreeBptHashMapTest, SmokeTestWithEraseSameHash) {
SmokeTestWithErase<DumbHash>(true);
SmokeTestWithErase<DumbHash>(false);
}

template <typename TREE>
void test_tree(TREE& tree) {
using Key = size_t;
using Value = size_t;
Key p{42};

// test various operations
tree.emplace(p, Value{2});
Value id3{3};
tree.emplace(p, id3);
ASSERT_EQ(tree.size(), 1u);

auto q_extent = tree.begin();
ASSERT_NE(q_extent, tree.end());
++q_extent;
ASSERT_EQ(q_extent, tree.end());

tree.erase(p);
ASSERT_EQ(0u, tree.size());
tree.erase(p);
ASSERT_EQ(0u, tree.size());
ASSERT_TRUE(tree.empty());
}

TEST(PhTreeBptHashMapTest, TestCopyConstruct) {
using TestTree = b_plus_tree_hash_map<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{tree1};
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptHashMapTest, TestCopyAssign) {
using TestTree = b_plus_tree_hash_map<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = tree1;
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptHashMapTest, TestMoveConstruct) {
using TestTree = b_plus_tree_hash_map<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{std::move(tree1)};
test_tree(tree);
}

TEST(PhTreeBptHashMapTest, TestMoveAssign) {
using TestTree = b_plus_tree_hash_map<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = std::move(tree1);
test_tree(tree);
}

TEST(PhTreeBptHashMapTest, TestMovableIterators) {
using Key = size_t;
using Value = size_t;
using TestTree = b_plus_tree_hash_map<Key, Value>;
// Test edge case: only one entry in tree
Key p{42};
auto tree = TestTree();
tree.emplace(p, Value{1});

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.begin())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.begin())>);
ASSERT_NE(tree.begin(), tree.end());

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.end())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.end())>);

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.find(p))>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.find(p))>);
ASSERT_NE(tree.find(p), tree.end());
}
87 changes: 87 additions & 0 deletions test/common/b_plus_tree_map_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,90 @@ TEST(PhTreeBptMapTest, SmokeTestLowerBound) {
}
}
}

template <typename TREE>
void test_tree(TREE& tree) {
using Key = size_t;
using Value = size_t;
Key p{42};

// test various operations
tree.emplace(p, Value{2});
Value id3{3};
tree.emplace(p, id3);
ASSERT_EQ(tree.size(), 1u);

auto q_extent = tree.begin();
ASSERT_NE(q_extent, tree.end());
++q_extent;
ASSERT_EQ(q_extent, tree.end());

tree.erase(p);
ASSERT_EQ(0u, tree.size());
tree.erase(p);
ASSERT_EQ(0u, tree.size());
ASSERT_TRUE(tree.empty());
}

TEST(PhTreeBptMapTest, TestCopyConstruct) {
using TestTree = b_plus_tree_map<size_t, size_t, 16>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{tree1};
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptMapTest, TestCopyAssign) {
using TestTree = b_plus_tree_map<size_t, size_t, 16>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = tree1;
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptMapTest, TestMoveConstruct) {
using TestTree = b_plus_tree_map<size_t, size_t, 16>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{std::move(tree1)};
test_tree(tree);
}

TEST(PhTreeBptMapTest, TestMoveAssign) {
using TestTree = b_plus_tree_map<size_t, size_t, 16>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = std::move(tree1);
test_tree(tree);
}

TEST(PhTreeBptMapTest, TestMovableIterators) {
using Key = size_t;
using Value = size_t;
using TestTree = b_plus_tree_map<Key, Value, 16>;
// Test edge case: only one entry in tree
Key p{42};
auto tree = TestTree();
tree.emplace(p, Value{1});

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.begin())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.begin())>);
ASSERT_NE(tree.begin(), tree.end());

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.end())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.end())>);

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.find(p))>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.find(p))>);
ASSERT_NE(tree.find(p), tree.end());
}
91 changes: 91 additions & 0 deletions test/common/b_plus_tree_multimap_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,94 @@ TEST(PhTreeBptMulitmapTest, SmokeTestUpdateByIterator) {
}
}
}

template <typename TREE>
void test_tree(TREE& tree) {
using Key = size_t;
using Value = size_t;
Key p{42};

// test various operations
tree.emplace(p, Value{2});
Value id3{3};
tree.emplace(p, id3);
ASSERT_EQ(tree.size(), 3u);

auto q_extent = tree.begin();
ASSERT_NE(q_extent, tree.end());
++q_extent;
ASSERT_NE(q_extent, tree.end());
++q_extent;
ASSERT_NE(q_extent, tree.end());
++q_extent;
ASSERT_EQ(q_extent, tree.end());

ASSERT_EQ(3u, tree.erase(p));
ASSERT_EQ(0u, tree.size());
ASSERT_EQ(0u, tree.erase(p));
ASSERT_EQ(0u, tree.size());
ASSERT_TRUE(tree.empty());
}

TEST(PhTreeBptMulitmapTest, TestCopyConstruct) {
using TestTree = b_plus_tree_multimap<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{tree1};
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptMulitmapTest, TestCopyAssign) {
using TestTree = b_plus_tree_multimap<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = tree1;
test_tree(tree);
// The old tree should still work!
test_tree(tree1);
}

TEST(PhTreeBptMulitmapTest, TestMoveConstruct) {
using TestTree = b_plus_tree_multimap<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{std::move(tree1)};
test_tree(tree);
}

TEST(PhTreeBptMulitmapTest, TestMoveAssign) {
using TestTree = b_plus_tree_multimap<size_t, size_t>;
TestTree tree1;
tree1.emplace(42, 1);

TestTree tree{};
tree = std::move(tree1);
test_tree(tree);
}

TEST(PhTreeBptMulitmapTest, TestMovableIterators) {
using Key = size_t;
using Value = size_t;
using TestTree = b_plus_tree_multimap<Key, Value>;
// Test edge case: only one entry in tree
Key p{42};
auto tree = TestTree();
tree.emplace(p, Value{1});

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.begin())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.begin())>);
ASSERT_NE(tree.begin(), tree.end());

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.end())>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.end())>);

ASSERT_TRUE(std::is_move_constructible_v<decltype(tree.find(p))>);
ASSERT_TRUE(std::is_move_assignable_v<decltype(tree.find(p))>);
ASSERT_NE(tree.find(p), tree.end());
}
2 changes: 0 additions & 2 deletions test/phtree_multimap_d_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,6 @@ TEST(PhTreeMMDTest, TestMoveConstruct) {

TestTree<3, Id> tree{std::move(tree1)};
test_tree(tree);
tree.~PhTreeMultiMap();
}

TEST(PhTreeMMDTest, TestMoveAssign) {
Expand All @@ -1260,7 +1259,6 @@ TEST(PhTreeMMDTest, TestMoveAssign) {
TestTree<3, Id> tree{};
tree = std::move(tree1);
test_tree(tree);
tree.~PhTreeMultiMap();
}

TEST(PhTreeMMDTest, TestMovableIterators) {
Expand Down
3 changes: 0 additions & 3 deletions test/phtree_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,6 @@ TEST(PhTreeTest, TestMoveConstruct) {

TestTree<3, Id> tree{std::move(tree1)};
test_tree(tree);
tree.~PhTree();
}

TEST(PhTreeTest, TestMoveAssign) {
Expand All @@ -1297,7 +1296,6 @@ TEST(PhTreeTest, TestMoveAssign) {
TestTree<3, Id> tree{};
tree = std::move(tree1);
test_tree(tree);
tree.~PhTree();
}

size_t count_pre{0};
Expand Down Expand Up @@ -1351,7 +1349,6 @@ TEST(PhTreeTest, TestMoveAssignCustomConverter) {
test_tree(tree);
ASSERT_GE(tree.converter().count_pre_local, 2);
ASSERT_EQ(tree.converter().count_pre_local, count_pre);
tree.~PhTree();
}

TEST(PhTreeTest, TestMovableIterators) {
Expand Down