Skip to content

Commit 4daf83d

Browse files
committed
Added tree hooking.
1 parent 62aa56d commit 4daf83d

File tree

8 files changed

+375
-51
lines changed

8 files changed

+375
-51
lines changed

CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ if(INT_TREE_DRAW_EXAMPLES)
1414
endif()
1515
if (INT_TREE_ENABLE_TESTS)
1616
add_subdirectory(tests)
17-
endif()
18-
17+
endif()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#if defined(__cpp_concepts) && __cpp_concepts >= 202002L
4+
# define LIB_INTERVAL_TREE_CONCEPTS
5+
#endif
6+
7+
namespace lib_interval_tree
8+
{
9+
}

include/interval-tree/interval_tree.hpp

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "interval_tree_fwd.hpp"
44
#include "interval_types.hpp"
5+
#include "tree_hooks.hpp"
56

67
#include <string>
78
#include <memory>
@@ -25,12 +26,13 @@ namespace lib_interval_tree
2526
// ############################################################################################################
2627
using default_interval_value_type = int;
2728
// ############################################################################################################
28-
template <typename numerical_type, typename interval_kind_ = closed>
29+
template <typename numerical_type, typename interval_kind_ = closed, typename tree_hooks = hooks::regular>
2930
struct interval
3031
{
3132
public:
3233
using value_type = numerical_type;
3334
using interval_kind = interval_kind_;
35+
friend tree_hooks;
3436

3537
/**
3638
* Constructs an interval. low MUST be smaller than high.
@@ -178,7 +180,7 @@ namespace lib_interval_tree
178180
/**
179181
* Creates a safe interval that puts the lower bound left automatically.
180182
*/
181-
template <typename numerical_type, typename interval_kind_ = closed>
183+
template <typename numerical_type, typename interval_kind_ = closed, typename tree_hooks = hooks::regular>
182184
#if __cplusplus >= 201703L
183185
constexpr
184186
#endif
@@ -190,7 +192,8 @@ namespace lib_interval_tree
190192
// ############################################################################################################
191193
template <
192194
typename numerical_type = default_interval_value_type,
193-
typename interval_type_ = interval<numerical_type, closed>>
195+
typename interval_type_ = interval<numerical_type, closed, hooks::regular>,
196+
typename tree_hooks = hooks::regular>
194197
class node
195198
{
196199
private:
@@ -199,13 +202,15 @@ namespace lib_interval_tree
199202
public:
200203
using interval_type = interval_type_;
201204
using value_type = numerical_type;
205+
using tree_hooks_type = tree_hooks;
206+
friend tree_hooks_type;
202207

203208
public:
204-
friend lib_interval_tree::interval_tree<interval_type>;
205-
friend lib_interval_tree::const_interval_tree_iterator<node<numerical_type, interval_type>, true>;
206-
friend lib_interval_tree::const_interval_tree_iterator<node<numerical_type, interval_type>, false>;
207-
friend lib_interval_tree::interval_tree_iterator<node<numerical_type, interval_type>, true>;
208-
friend lib_interval_tree::interval_tree_iterator<node<numerical_type, interval_type>, false>;
209+
friend lib_interval_tree::interval_tree<interval_type, tree_hooks>;
210+
friend lib_interval_tree::const_interval_tree_iterator<node<numerical_type, interval_type, tree_hooks>, true>;
211+
friend lib_interval_tree::const_interval_tree_iterator<node<numerical_type, interval_type, tree_hooks>, false>;
212+
friend lib_interval_tree::interval_tree_iterator<node<numerical_type, interval_type, tree_hooks>, true>;
213+
friend lib_interval_tree::interval_tree_iterator<node<numerical_type, interval_type, tree_hooks>, false>;
209214

210215
template <typename T>
211216
friend void increment(T& iter);
@@ -344,9 +349,11 @@ namespace lib_interval_tree
344349
class basic_interval_tree_iterator : public std::forward_iterator_tag
345350
{
346351
public:
347-
friend interval_tree<typename node_type::interval_type>;
352+
friend interval_tree<typename node_type::interval_type, typename node_type::tree_hooks_type>;
353+
friend typename node_type::tree_hooks_type;
348354

349-
using tree_type = interval_tree<typename node_type::interval_type>;
355+
using tree_hooks_type = typename node_type::tree_hooks_type;
356+
using tree_type = interval_tree<typename node_type::interval_type, tree_hooks_type>;
350357
using value_type = node_type;
351358

352359
using node_ptr_t = typename std::conditional<
@@ -416,16 +423,20 @@ namespace lib_interval_tree
416423
// ############################################################################################################
417424
template <typename node_type, bool reverse>
418425
class const_interval_tree_iterator
419-
: public basic_interval_tree_iterator<node_type, interval_tree<typename node_type::interval_type> const*>
426+
: public basic_interval_tree_iterator<
427+
node_type,
428+
interval_tree<typename node_type::interval_type, typename node_type::tree_hooks_type> const*>
420429
{
421430
public:
422-
using tree_type = interval_tree<typename node_type::interval_type>;
431+
using tree_hooks_type = typename node_type::tree_hooks_type;
432+
using tree_type = interval_tree<typename node_type::interval_type, tree_hooks_type>;
423433
using iterator_base = basic_interval_tree_iterator<node_type, tree_type const*>;
424434
using value_type = typename iterator_base::value_type;
425435
using iterator_base::node_;
426436
using iterator_base::owner_;
427437

428438
friend tree_type;
439+
friend tree_hooks_type;
429440

430441
public:
431442
~const_interval_tree_iterator() = default;
@@ -519,16 +530,20 @@ namespace lib_interval_tree
519530
// ############################################################################################################
520531
template <typename node_type, bool reverse = false>
521532
class interval_tree_iterator
522-
: public basic_interval_tree_iterator<node_type, interval_tree<typename node_type::interval_type>*>
533+
: public basic_interval_tree_iterator<
534+
node_type,
535+
interval_tree<typename node_type::interval_type, typename node_type::tree_hooks_type>*>
523536
{
524537
public:
525-
using tree_type = interval_tree<typename node_type::interval_type>;
538+
using tree_hooks_type = typename node_type::tree_hooks_type;
539+
using tree_type = interval_tree<typename node_type::interval_type, tree_hooks_type>;
526540
using iterator_base = basic_interval_tree_iterator<node_type, tree_type*>;
527541
using value_type = typename iterator_base::value_type;
528542
using iterator_base::node_;
529543
using iterator_base::owner_;
530544

531545
friend tree_type;
546+
friend tree_hooks_type;
532547

533548
public:
534549
~interval_tree_iterator() = default;
@@ -685,25 +700,40 @@ namespace lib_interval_tree
685700
}
686701
}
687702
// ############################################################################################################
688-
template <typename IntervalT = interval<int, closed>>
689-
class interval_tree
703+
template <typename IntervalT = interval<int, closed>, typename tree_hooks = hooks::regular>
704+
class interval_tree : public tree_hooks::hook_state
690705
{
691706
public:
692707
using interval_type = IntervalT;
708+
using tree_hooks_type = tree_hooks;
693709
using value_type = typename interval_type::value_type;
694-
using node_type = node<value_type, interval_type>;
710+
711+
// Node type:
712+
using node_type = std::conditional_t<
713+
std::is_same_v<typename tree_hooks::node_type, void>,
714+
node<value_type, interval_type, tree_hooks>,
715+
typename tree_hooks::node_type>;
716+
717+
// Iterators:
695718
using iterator = interval_tree_iterator<node_type, false>;
696719
using const_iterator = const_interval_tree_iterator<node_type, false>;
697720
using reverse_iterator = interval_tree_iterator<node_type, true>;
698721
using const_reverse_iterator = const_interval_tree_iterator<node_type, true>;
699-
using size_type = long long;
700-
using this_type = interval_tree<interval_type>;
722+
723+
// Size type:
724+
using size_type = std::conditional_t<
725+
std::is_same_v<typename tree_hooks::size_type, void>,
726+
long long,
727+
typename tree_hooks::size_type>;
728+
729+
using this_type = interval_tree<interval_type, tree_hooks>;
701730

702731
public:
703732
friend const_interval_tree_iterator<node_type, true>;
704733
friend const_interval_tree_iterator<node_type, false>;
705734
friend interval_tree_iterator<node_type, true>;
706735
friend interval_tree_iterator<node_type, false>;
736+
friend tree_hooks;
707737

708738
template <typename T>
709739
friend void increment(T& iter);
@@ -718,6 +748,7 @@ namespace lib_interval_tree
718748

719749
~interval_tree()
720750
{
751+
tree_hooks::template on_destroy<this_type>(*this);
721752
clear();
722753
}
723754

@@ -815,6 +846,7 @@ namespace lib_interval_tree
815846

816847
insert_fixup(z);
817848
recalculate_max(z);
849+
818850
++size_;
819851
return {z, this};
820852
}
@@ -1331,6 +1363,7 @@ namespace lib_interval_tree
13311363
ComparatorFunctionT const& compare
13321364
)
13331365
{
1366+
std::decay_t<ThisType>::tree_hooks_type::template on_find_all<this_type>(*self, ptr, ival, compare);
13341367
if (compare(*ptr->interval(), ival))
13351368
{
13361369
if (!on_find(IteratorT{ptr, self}))
@@ -1359,6 +1392,7 @@ namespace lib_interval_tree
13591392
template <typename ComparatorFunctionT>
13601393
node_type* find_i(node_type* ptr, interval_type const& ival, ComparatorFunctionT const& compare) const
13611394
{
1395+
tree_hooks::template on_find<this_type>(*this, ptr, ival, compare);
13621396
if (compare(*ptr->interval(), ival))
13631397
return ptr;
13641398
else
@@ -1394,6 +1428,7 @@ namespace lib_interval_tree
13941428
template <bool Exclusive>
13951429
node_type* overlap_find_i(node_type* ptr, interval_type const& ival) const
13961430
{
1431+
tree_hooks::template on_overlap_find<this_type>(*this, ptr, ival);
13971432
#if __cplusplus >= 201703L
13981433
if constexpr (Exclusive)
13991434
#else
@@ -1420,6 +1455,7 @@ namespace lib_interval_tree
14201455
FunctionT const& on_find
14211456
)
14221457
{
1458+
std::decay_t<ThisType>::tree_hooks_type::template on_overlap_find_all<ThisType>(*self, ptr, ival);
14231459
#if __cplusplus >= 201703L
14241460
if constexpr (Exclusive)
14251461
#else
@@ -1505,30 +1541,6 @@ namespace lib_interval_tree
15051541
return y;
15061542
}
15071543

1508-
bool is_descendant(iterator par, iterator desc)
1509-
{
1510-
auto p = desc->parent_;
1511-
for (; p && p != par.node_; p = p->parent_)
1512-
{}
1513-
return p != nullptr;
1514-
}
1515-
1516-
/**
1517-
* Set v inplace of u. Does not delete u.
1518-
* Creates orphaned nodes. A transplant call must be succeeded by delete calls.
1519-
*/
1520-
void transplant(node_type* u, node_type* v)
1521-
{
1522-
if (u->is_root())
1523-
root_ = v;
1524-
else if (u->is_left())
1525-
u->parent_->left_ = v;
1526-
else
1527-
u->parent_->right_ = v;
1528-
if (v)
1529-
v->parent_ = u->parent_;
1530-
}
1531-
15321544
/**
15331545
* Get leftest of x.
15341546
*/
@@ -1610,6 +1622,8 @@ namespace lib_interval_tree
16101622

16111623
void recalculate_max(node_type* reacalculation_root)
16121624
{
1625+
tree_hooks::template on_before_recalculate_max<this_type>(*this, reacalculation_root);
1626+
16131627
auto* p = reacalculation_root;
16141628
while (p && p->max_ <= reacalculation_root->max_)
16151629
{
@@ -1619,10 +1633,14 @@ namespace lib_interval_tree
16191633
p->max_ = p->right_->max_;
16201634
p = p->parent_;
16211635
}
1636+
1637+
tree_hooks::template on_after_recalculate_max<this_type>(*this, reacalculation_root);
16221638
}
16231639

16241640
void insert_fixup(node_type* z)
16251641
{
1642+
tree_hooks::template on_before_insert_fixup<this_type>(*this, z);
1643+
16261644
while (z->parent_ && z->parent_->color_ == rb_color::red)
16271645
{
16281646
if (!z->parent_->parent_)
@@ -1673,10 +1691,14 @@ namespace lib_interval_tree
16731691
}
16741692
}
16751693
root_->color_ = rb_color::black;
1694+
1695+
tree_hooks::template on_after_insert_fixup<this_type>(*this, z);
16761696
}
16771697

16781698
void erase_fixup(node_type* x, node_type* x_parent, bool y_is_left)
16791699
{
1700+
tree_hooks::template on_before_erase_fixup<this_type>(*this, x, x_parent, y_is_left);
1701+
16801702
while (x != root_ && x->color_ == rb_color::black)
16811703
{
16821704
node_type* w;
@@ -1759,14 +1781,16 @@ namespace lib_interval_tree
17591781
}
17601782

17611783
x->color_ = rb_color::black;
1784+
1785+
tree_hooks::template on_after_erase_fixup<this_type>(*this, x, x_parent, y_is_left);
17621786
}
17631787

17641788
private:
17651789
node_type* root_;
17661790
size_type size_;
17671791
};
17681792
// ############################################################################################################
1769-
template <typename T, typename Kind = closed>
1770-
using interval_tree_t = interval_tree<interval<T, Kind>>;
1793+
template <typename T, typename Kind = closed, typename tree_hooks = hooks::regular>
1794+
using interval_tree_t = interval_tree<interval<T, Kind>, tree_hooks>;
17711795
// ############################################################################################################
17721796
}

include/interval-tree/interval_tree_fwd.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
namespace lib_interval_tree
44
{
5-
template <typename numerical_type, typename interval_kind_>
5+
template <typename numerical_type, typename interval_kind_, typename tree_hooks>
66
struct interval;
77

8-
template <typename IntervalT>
8+
template <typename IntervalT, typename tree_hooks>
99
class interval_tree;
1010

11-
template <typename numerical_type, typename interval_type>
11+
template <typename numerical_type, typename interval_type, typename tree_hooks>
1212
class node;
1313

1414
template <typename node_type, typename owner_type>

0 commit comments

Comments
 (0)