xref: /kvmtool/util/rbtree-interval.c (revision e358b4fbdbde26dd1b7d8198db856a8cb65c1eec)
1*e358b4fbSSasha Levin #include <kvm/rbtree-interval.h>
2*e358b4fbSSasha Levin #include <stddef.h>
3*e358b4fbSSasha Levin 
4*e358b4fbSSasha Levin #define rb_int(n) rb_entry(n, struct rb_int_node, node)
5*e358b4fbSSasha Levin 
6*e358b4fbSSasha Levin struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point)
7*e358b4fbSSasha Levin {
8*e358b4fbSSasha Levin 	struct rb_node *node = root->rb_node;
9*e358b4fbSSasha Levin 	struct rb_node *lowest = NULL;
10*e358b4fbSSasha Levin 
11*e358b4fbSSasha Levin 	while (node) {
12*e358b4fbSSasha Levin 		struct rb_int_node *cur = rb_int(node);
13*e358b4fbSSasha Levin 
14*e358b4fbSSasha Levin 		if (node->rb_left && (rb_int(node->rb_left)->max_high > point)) {
15*e358b4fbSSasha Levin 			node = node->rb_left;
16*e358b4fbSSasha Levin 		} else if (cur->low <= point && cur->high > point) {
17*e358b4fbSSasha Levin 			lowest = node;
18*e358b4fbSSasha Levin 			break;
19*e358b4fbSSasha Levin 		} else if (point > cur->low) {
20*e358b4fbSSasha Levin 			node = node->rb_right;
21*e358b4fbSSasha Levin 		} else {
22*e358b4fbSSasha Levin 			break;
23*e358b4fbSSasha Levin 		}
24*e358b4fbSSasha Levin 	}
25*e358b4fbSSasha Levin 
26*e358b4fbSSasha Levin 	if (lowest == NULL)
27*e358b4fbSSasha Levin 		return NULL;
28*e358b4fbSSasha Levin 
29*e358b4fbSSasha Levin 	return rb_int(lowest);
30*e358b4fbSSasha Levin }
31*e358b4fbSSasha Levin 
32*e358b4fbSSasha Levin struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high)
33*e358b4fbSSasha Levin {
34*e358b4fbSSasha Levin 	struct rb_int_node *range;
35*e358b4fbSSasha Levin 
36*e358b4fbSSasha Levin 	range = rb_int_search_single(root, low);
37*e358b4fbSSasha Levin 	if (range == NULL)
38*e358b4fbSSasha Levin 		return NULL;
39*e358b4fbSSasha Levin 
40*e358b4fbSSasha Levin 	/* We simply verify that 'high' is smaller than the end of the range where 'low' is located */
41*e358b4fbSSasha Levin 	if (range->high < high)
42*e358b4fbSSasha Levin 		return NULL;
43*e358b4fbSSasha Levin 
44*e358b4fbSSasha Levin 	return range;
45*e358b4fbSSasha Levin }
46*e358b4fbSSasha Levin 
47*e358b4fbSSasha Levin static void update_node_max_high(struct rb_node *node, void *arg)
48*e358b4fbSSasha Levin {
49*e358b4fbSSasha Levin 	struct rb_int_node *i_node = rb_int(node);
50*e358b4fbSSasha Levin 
51*e358b4fbSSasha Levin 	i_node->max_high = i_node->high;
52*e358b4fbSSasha Levin 
53*e358b4fbSSasha Levin 	if (node->rb_left)
54*e358b4fbSSasha Levin 		i_node->max_high = max(i_node->max_high, rb_int(node->rb_left)->high);
55*e358b4fbSSasha Levin 	if (node->rb_right)
56*e358b4fbSSasha Levin 		i_node->max_high = max(i_node->max_high, rb_int(node->rb_right)->high);
57*e358b4fbSSasha Levin }
58*e358b4fbSSasha Levin 
59*e358b4fbSSasha Levin int rb_int_insert(struct rb_root *root, struct rb_int_node *i_node)
60*e358b4fbSSasha Levin {
61*e358b4fbSSasha Levin 	struct rb_node **node	= &(root->rb_node), *parent = NULL;
62*e358b4fbSSasha Levin 
63*e358b4fbSSasha Levin 	while (*node) {
64*e358b4fbSSasha Levin 		int result	= i_node->low - rb_int(*node)->low;
65*e358b4fbSSasha Levin 
66*e358b4fbSSasha Levin 		parent = *node;
67*e358b4fbSSasha Levin 		if (result < 0)
68*e358b4fbSSasha Levin 			node	= &((*node)->rb_left);
69*e358b4fbSSasha Levin 		else if (result > 0)
70*e358b4fbSSasha Levin 			node	= &((*node)->rb_right);
71*e358b4fbSSasha Levin 		else
72*e358b4fbSSasha Levin 			return 0;
73*e358b4fbSSasha Levin 	}
74*e358b4fbSSasha Levin 
75*e358b4fbSSasha Levin 	rb_link_node(&i_node->node, parent, node);
76*e358b4fbSSasha Levin 	rb_insert_color(&i_node->node, root);
77*e358b4fbSSasha Levin 
78*e358b4fbSSasha Levin 	rb_augment_insert(*node, update_node_max_high, NULL);
79*e358b4fbSSasha Levin 	return 1;
80*e358b4fbSSasha Levin }
81*e358b4fbSSasha Levin 
82*e358b4fbSSasha Levin void rb_int_erase(struct rb_root *root, struct rb_int_node *node)
83*e358b4fbSSasha Levin {
84*e358b4fbSSasha Levin 	struct rb_node *deepest;
85*e358b4fbSSasha Levin 
86*e358b4fbSSasha Levin 	deepest = rb_augment_erase_begin(&node->node);
87*e358b4fbSSasha Levin 	rb_erase(&node->node, root);
88*e358b4fbSSasha Levin 	rb_augment_erase_end(deepest, update_node_max_high, NULL);
89*e358b4fbSSasha Levin 
90*e358b4fbSSasha Levin }
91