1 /* Ordered map data type implemented by a binary tree.
2 Copyright (C) 2006-2007, 2009-2019 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2018.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Common code of gl_avltree_omap.c and gl_rbtree_omap.c. */
20 /* An item on the stack used for iterating across the elements. */
27 /* A stack used for iterating across the elements. */
28 typedef iterstack_item_t iterstack_t
[MAXHEIGHT
];
31 gl_tree_nx_create_empty (gl_omap_implementation_t implementation
,
32 gl_mapkey_compar_fn compar_fn
,
33 gl_mapkey_dispose_fn kdispose_fn
,
34 gl_mapvalue_dispose_fn vdispose_fn
)
36 struct gl_omap_impl
*map
=
37 (struct gl_omap_impl
*) malloc (sizeof (struct gl_omap_impl
));
42 map
->base
.vtable
= implementation
;
43 map
->base
.compar_fn
= compar_fn
;
44 map
->base
.kdispose_fn
= kdispose_fn
;
45 map
->base
.vdispose_fn
= vdispose_fn
;
53 gl_tree_size (gl_omap_t map
)
59 gl_tree_search (gl_omap_t map
, const void *key
, const void **valuep
)
61 gl_mapkey_compar_fn compar
= map
->base
.compar_fn
;
64 for (node
= map
->root
; node
!= NULL
; )
66 int cmp
= (compar
!= NULL
67 ? compar (node
->key
, key
)
68 : (node
->key
> key
? 1 :
69 node
->key
< key
? -1 : 0));
77 /* We have a key equal to KEY. */
78 *valuep
= node
->value
;
86 gl_tree_search_atleast (gl_omap_t map
,
87 gl_mapkey_threshold_fn threshold_fn
,
88 const void *threshold
,
89 const void **keyp
, const void **valuep
)
93 for (node
= map
->root
; node
!= NULL
; )
95 if (! threshold_fn (node
->key
, threshold
))
99 /* We have a key >= THRESHOLD. But we need the leftmost such
101 gl_omap_node_t found
= node
;
103 for (; node
!= NULL
; )
105 if (! threshold_fn (node
->key
, threshold
))
114 *valuep
= found
->value
;
122 gl_tree_nx_getput (gl_omap_t map
, const void *key
, const void *value
,
123 const void **oldvaluep
)
125 gl_mapkey_compar_fn compar
;
126 gl_omap_node_t node
= map
->root
;
130 if (gl_tree_nx_add_first (map
, key
, value
) == NULL
)
135 compar
= map
->base
.compar_fn
;
139 int cmp
= (compar
!= NULL
140 ? compar (node
->key
, key
)
141 : (node
->key
> key
? 1 :
142 node
->key
< key
? -1 : 0));
146 if (node
->right
== NULL
)
148 if (gl_tree_nx_add_after (map
, node
, key
, value
) == NULL
)
156 if (node
->left
== NULL
)
158 if (gl_tree_nx_add_before (map
, node
, key
, value
) == NULL
)
166 *oldvaluep
= node
->value
;
174 gl_tree_getremove (gl_omap_t map
, const void *key
, const void **oldvaluep
)
176 gl_mapkey_compar_fn compar
= map
->base
.compar_fn
;
179 for (node
= map
->root
; node
!= NULL
; )
181 int cmp
= (compar
!= NULL
182 ? compar (node
->key
, key
)
183 : (node
->key
> key
? 1 :
184 node
->key
< key
? -1 : 0));
192 /* We have a key equal to KEY. */
193 *oldvaluep
= node
->value
;
194 gl_tree_remove_node (map
, node
);
202 gl_tree_omap_free (gl_omap_t map
)
204 /* Iterate across all elements in post-order. */
205 gl_omap_node_t node
= map
->root
;
207 iterstack_item_t
*stack_ptr
= &stack
[0];
211 /* Descend on left branch. */
216 stack_ptr
->node
= node
;
217 stack_ptr
->rightp
= false;
221 /* Climb up again. */
224 if (stack_ptr
== &stack
[0])
227 node
= stack_ptr
->node
;
228 if (!stack_ptr
->rightp
)
230 /* Free the current node. */
231 if (map
->base
.vdispose_fn
!= NULL
)
232 map
->base
.vdispose_fn (node
->value
);
233 if (map
->base
.kdispose_fn
!= NULL
)
234 map
->base
.kdispose_fn (node
->key
);
237 /* Descend on right branch. */
238 stack_ptr
->rightp
= true;
246 /* --------------------- gl_omap_iterator_t Data Type --------------------- */
248 static gl_omap_iterator_t
249 gl_tree_iterator (gl_omap_t map
)
251 gl_omap_iterator_t result
;
254 result
.vtable
= map
->base
.vtable
;
256 /* Start node is the leftmost node. */
259 while (node
->left
!= NULL
)
262 /* End point is past the rightmost node. */
264 #if defined GCC_LINT || defined lint
274 gl_tree_iterator_next (gl_omap_iterator_t
*iterator
,
275 const void **keyp
, const void **valuep
)
277 if (iterator
->p
!= iterator
->q
)
279 gl_omap_node_t node
= (gl_omap_node_t
) iterator
->p
;
281 *valuep
= node
->value
;
282 /* Advance to the next node. */
283 if (node
->right
!= NULL
)
286 while (node
->left
!= NULL
)
291 while (node
->parent
!= NULL
&& node
->parent
->right
== node
)
303 gl_tree_iterator_free (gl_omap_iterator_t
*iterator
)