1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky *
6*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
7*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
8*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
9*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
10*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
11*d6b92ffaSHans Petter Selasky *
12*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
13*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
14*d6b92ffaSHans Petter Selasky * conditions are met:
15*d6b92ffaSHans Petter Selasky *
16*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
17*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky * disclaimer.
19*d6b92ffaSHans Petter Selasky *
20*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
21*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
22*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
23*d6b92ffaSHans Petter Selasky * provided with the distribution.
24*d6b92ffaSHans Petter Selasky *
25*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*d6b92ffaSHans Petter Selasky * SOFTWARE.
33*d6b92ffaSHans Petter Selasky *
34*d6b92ffaSHans Petter Selasky */
35*d6b92ffaSHans Petter Selasky
36*d6b92ffaSHans Petter Selasky /*
37*d6b92ffaSHans Petter Selasky * Abstract:
38*d6b92ffaSHans Petter Selasky * Implementation of quick map, a binary tree where the caller always
39*d6b92ffaSHans Petter Selasky * provides all necessary storage.
40*d6b92ffaSHans Petter Selasky *
41*d6b92ffaSHans Petter Selasky */
42*d6b92ffaSHans Petter Selasky
43*d6b92ffaSHans Petter Selasky /*****************************************************************************
44*d6b92ffaSHans Petter Selasky *
45*d6b92ffaSHans Petter Selasky * Map
46*d6b92ffaSHans Petter Selasky *
47*d6b92ffaSHans Petter Selasky * Map is an associative array. By providing a key, the caller can retrieve
48*d6b92ffaSHans Petter Selasky * an object from the map. All objects in the map have an associated key,
49*d6b92ffaSHans Petter Selasky * as specified by the caller when the object was inserted into the map.
50*d6b92ffaSHans Petter Selasky * In addition to random access, the caller can traverse the map much like
51*d6b92ffaSHans Petter Selasky * a linked list, either forwards from the first object or backwards from
52*d6b92ffaSHans Petter Selasky * the last object. The objects in the map are always traversed in
53*d6b92ffaSHans Petter Selasky * order since the nodes are stored sorted.
54*d6b92ffaSHans Petter Selasky *
55*d6b92ffaSHans Petter Selasky * This implementation of Map uses a red black tree verified against
56*d6b92ffaSHans Petter Selasky * Cormen-Leiserson-Rivest text, McGraw-Hill Edition, fourteenth
57*d6b92ffaSHans Petter Selasky * printing, 1994.
58*d6b92ffaSHans Petter Selasky *
59*d6b92ffaSHans Petter Selasky *****************************************************************************/
60*d6b92ffaSHans Petter Selasky
61*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
62*d6b92ffaSHans Petter Selasky # include <config.h>
63*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
64*d6b92ffaSHans Petter Selasky
65*d6b92ffaSHans Petter Selasky #include <string.h>
66*d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h>
67*d6b92ffaSHans Petter Selasky #include <complib/cl_map.h>
68*d6b92ffaSHans Petter Selasky #include <complib/cl_fleximap.h>
69*d6b92ffaSHans Petter Selasky
70*d6b92ffaSHans Petter Selasky /******************************************************************************
71*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF QUICK MAP
72*d6b92ffaSHans Petter Selasky ******************************************************************************/
73*d6b92ffaSHans Petter Selasky
74*d6b92ffaSHans Petter Selasky /*
75*d6b92ffaSHans Petter Selasky * Get the root.
76*d6b92ffaSHans Petter Selasky */
__cl_map_root(IN const cl_qmap_t * const p_map)77*d6b92ffaSHans Petter Selasky static inline cl_map_item_t *__cl_map_root(IN const cl_qmap_t * const p_map)
78*d6b92ffaSHans Petter Selasky {
79*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
80*d6b92ffaSHans Petter Selasky return (p_map->root.p_left);
81*d6b92ffaSHans Petter Selasky }
82*d6b92ffaSHans Petter Selasky
83*d6b92ffaSHans Petter Selasky /*
84*d6b92ffaSHans Petter Selasky * Returns whether a given item is on the left of its parent.
85*d6b92ffaSHans Petter Selasky */
__cl_map_is_left_child(IN const cl_map_item_t * const p_item)86*d6b92ffaSHans Petter Selasky static boolean_t __cl_map_is_left_child(IN const cl_map_item_t * const p_item)
87*d6b92ffaSHans Petter Selasky {
88*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
89*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up);
90*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item);
91*d6b92ffaSHans Petter Selasky
92*d6b92ffaSHans Petter Selasky return (p_item->p_up->p_left == p_item);
93*d6b92ffaSHans Petter Selasky }
94*d6b92ffaSHans Petter Selasky
95*d6b92ffaSHans Petter Selasky /*
96*d6b92ffaSHans Petter Selasky * Retrieve the pointer to the parent's pointer to an item.
97*d6b92ffaSHans Petter Selasky */
__cl_map_get_parent_ptr_to_item(IN cl_map_item_t * const p_item)98*d6b92ffaSHans Petter Selasky static cl_map_item_t **__cl_map_get_parent_ptr_to_item(IN cl_map_item_t *
99*d6b92ffaSHans Petter Selasky const p_item)
100*d6b92ffaSHans Petter Selasky {
101*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
102*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up);
103*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item);
104*d6b92ffaSHans Petter Selasky
105*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item))
106*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_left);
107*d6b92ffaSHans Petter Selasky
108*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up->p_right == p_item);
109*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_right);
110*d6b92ffaSHans Petter Selasky }
111*d6b92ffaSHans Petter Selasky
112*d6b92ffaSHans Petter Selasky /*
113*d6b92ffaSHans Petter Selasky * Rotate a node to the left. This rotation affects the least number of links
114*d6b92ffaSHans Petter Selasky * between nodes and brings the level of C up by one while increasing the depth
115*d6b92ffaSHans Petter Selasky * of A one. Note that the links to/from W, X, Y, and Z are not affected.
116*d6b92ffaSHans Petter Selasky *
117*d6b92ffaSHans Petter Selasky * R R
118*d6b92ffaSHans Petter Selasky * | |
119*d6b92ffaSHans Petter Selasky * A C
120*d6b92ffaSHans Petter Selasky * / \ / \
121*d6b92ffaSHans Petter Selasky * W C A Z
122*d6b92ffaSHans Petter Selasky * / \ / \
123*d6b92ffaSHans Petter Selasky * B Z W B
124*d6b92ffaSHans Petter Selasky * / \ / \
125*d6b92ffaSHans Petter Selasky * X Y X Y
126*d6b92ffaSHans Petter Selasky */
__cl_map_rot_left(IN cl_qmap_t * const p_map,IN cl_map_item_t * const p_item)127*d6b92ffaSHans Petter Selasky static void __cl_map_rot_left(IN cl_qmap_t * const p_map,
128*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item)
129*d6b92ffaSHans Petter Selasky {
130*d6b92ffaSHans Petter Selasky cl_map_item_t **pp_root;
131*d6b92ffaSHans Petter Selasky
132*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
133*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
134*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_right != &p_map->nil);
135*d6b92ffaSHans Petter Selasky
136*d6b92ffaSHans Petter Selasky pp_root = __cl_map_get_parent_ptr_to_item(p_item);
137*d6b92ffaSHans Petter Selasky
138*d6b92ffaSHans Petter Selasky /* Point R to C instead of A. */
139*d6b92ffaSHans Petter Selasky *pp_root = p_item->p_right;
140*d6b92ffaSHans Petter Selasky /* Set C's parent to R. */
141*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up;
142*d6b92ffaSHans Petter Selasky
143*d6b92ffaSHans Petter Selasky /* Set A's right to B */
144*d6b92ffaSHans Petter Selasky p_item->p_right = (*pp_root)->p_left;
145*d6b92ffaSHans Petter Selasky /*
146*d6b92ffaSHans Petter Selasky * Set B's parent to A. We trap for B being NIL since the
147*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing.
148*d6b92ffaSHans Petter Selasky */
149*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_left != &p_map->nil)
150*d6b92ffaSHans Petter Selasky (*pp_root)->p_left->p_up = p_item;
151*d6b92ffaSHans Petter Selasky
152*d6b92ffaSHans Petter Selasky /* Set C's left to A. */
153*d6b92ffaSHans Petter Selasky (*pp_root)->p_left = p_item;
154*d6b92ffaSHans Petter Selasky /* Set A's parent to C. */
155*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root;
156*d6b92ffaSHans Petter Selasky }
157*d6b92ffaSHans Petter Selasky
158*d6b92ffaSHans Petter Selasky /*
159*d6b92ffaSHans Petter Selasky * Rotate a node to the right. This rotation affects the least number of links
160*d6b92ffaSHans Petter Selasky * between nodes and brings the level of A up by one while increasing the depth
161*d6b92ffaSHans Petter Selasky * of C one. Note that the links to/from W, X, Y, and Z are not affected.
162*d6b92ffaSHans Petter Selasky *
163*d6b92ffaSHans Petter Selasky * R R
164*d6b92ffaSHans Petter Selasky * | |
165*d6b92ffaSHans Petter Selasky * C A
166*d6b92ffaSHans Petter Selasky * / \ / \
167*d6b92ffaSHans Petter Selasky * A Z W C
168*d6b92ffaSHans Petter Selasky * / \ / \
169*d6b92ffaSHans Petter Selasky * W B B Z
170*d6b92ffaSHans Petter Selasky * / \ / \
171*d6b92ffaSHans Petter Selasky * X Y X Y
172*d6b92ffaSHans Petter Selasky */
__cl_map_rot_right(IN cl_qmap_t * const p_map,IN cl_map_item_t * const p_item)173*d6b92ffaSHans Petter Selasky static void __cl_map_rot_right(IN cl_qmap_t * const p_map,
174*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item)
175*d6b92ffaSHans Petter Selasky {
176*d6b92ffaSHans Petter Selasky cl_map_item_t **pp_root;
177*d6b92ffaSHans Petter Selasky
178*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
179*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
180*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_left != &p_map->nil);
181*d6b92ffaSHans Petter Selasky
182*d6b92ffaSHans Petter Selasky /* Point R to A instead of C. */
183*d6b92ffaSHans Petter Selasky pp_root = __cl_map_get_parent_ptr_to_item(p_item);
184*d6b92ffaSHans Petter Selasky (*pp_root) = p_item->p_left;
185*d6b92ffaSHans Petter Selasky /* Set A's parent to R. */
186*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up;
187*d6b92ffaSHans Petter Selasky
188*d6b92ffaSHans Petter Selasky /* Set C's left to B */
189*d6b92ffaSHans Petter Selasky p_item->p_left = (*pp_root)->p_right;
190*d6b92ffaSHans Petter Selasky /*
191*d6b92ffaSHans Petter Selasky * Set B's parent to C. We trap for B being NIL since the
192*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing.
193*d6b92ffaSHans Petter Selasky */
194*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_right != &p_map->nil)
195*d6b92ffaSHans Petter Selasky (*pp_root)->p_right->p_up = p_item;
196*d6b92ffaSHans Petter Selasky
197*d6b92ffaSHans Petter Selasky /* Set A's right to C. */
198*d6b92ffaSHans Petter Selasky (*pp_root)->p_right = p_item;
199*d6b92ffaSHans Petter Selasky /* Set C's parent to A. */
200*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root;
201*d6b92ffaSHans Petter Selasky }
202*d6b92ffaSHans Petter Selasky
cl_qmap_init(IN cl_qmap_t * const p_map)203*d6b92ffaSHans Petter Selasky void cl_qmap_init(IN cl_qmap_t * const p_map)
204*d6b92ffaSHans Petter Selasky {
205*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
206*d6b92ffaSHans Petter Selasky
207*d6b92ffaSHans Petter Selasky memset(p_map, 0, sizeof(cl_qmap_t));
208*d6b92ffaSHans Petter Selasky
209*d6b92ffaSHans Petter Selasky /* special setup for the root node */
210*d6b92ffaSHans Petter Selasky p_map->root.p_up = &p_map->root;
211*d6b92ffaSHans Petter Selasky p_map->root.p_left = &p_map->nil;
212*d6b92ffaSHans Petter Selasky p_map->root.p_right = &p_map->nil;
213*d6b92ffaSHans Petter Selasky p_map->root.color = CL_MAP_BLACK;
214*d6b92ffaSHans Petter Selasky
215*d6b92ffaSHans Petter Selasky /* Setup the node used as terminator for all leaves. */
216*d6b92ffaSHans Petter Selasky p_map->nil.p_up = &p_map->nil;
217*d6b92ffaSHans Petter Selasky p_map->nil.p_left = &p_map->nil;
218*d6b92ffaSHans Petter Selasky p_map->nil.p_right = &p_map->nil;
219*d6b92ffaSHans Petter Selasky p_map->nil.color = CL_MAP_BLACK;
220*d6b92ffaSHans Petter Selasky
221*d6b92ffaSHans Petter Selasky p_map->state = CL_INITIALIZED;
222*d6b92ffaSHans Petter Selasky
223*d6b92ffaSHans Petter Selasky cl_qmap_remove_all(p_map);
224*d6b92ffaSHans Petter Selasky }
225*d6b92ffaSHans Petter Selasky
cl_qmap_get(IN const cl_qmap_t * const p_map,IN const uint64_t key)226*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map,
227*d6b92ffaSHans Petter Selasky IN const uint64_t key)
228*d6b92ffaSHans Petter Selasky {
229*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
230*d6b92ffaSHans Petter Selasky
231*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
232*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
233*d6b92ffaSHans Petter Selasky
234*d6b92ffaSHans Petter Selasky p_item = __cl_map_root(p_map);
235*d6b92ffaSHans Petter Selasky
236*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) {
237*d6b92ffaSHans Petter Selasky if (key == p_item->key)
238*d6b92ffaSHans Petter Selasky break; /* just right */
239*d6b92ffaSHans Petter Selasky
240*d6b92ffaSHans Petter Selasky if (key < p_item->key)
241*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */
242*d6b92ffaSHans Petter Selasky else
243*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big */
244*d6b92ffaSHans Petter Selasky }
245*d6b92ffaSHans Petter Selasky
246*d6b92ffaSHans Petter Selasky return (p_item);
247*d6b92ffaSHans Petter Selasky }
248*d6b92ffaSHans Petter Selasky
cl_qmap_get_next(IN const cl_qmap_t * const p_map,IN const uint64_t key)249*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map,
250*d6b92ffaSHans Petter Selasky IN const uint64_t key)
251*d6b92ffaSHans Petter Selasky {
252*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
253*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item_found;
254*d6b92ffaSHans Petter Selasky
255*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
256*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
257*d6b92ffaSHans Petter Selasky
258*d6b92ffaSHans Petter Selasky p_item = __cl_map_root(p_map);
259*d6b92ffaSHans Petter Selasky p_item_found = (cl_map_item_t *) & p_map->nil;
260*d6b92ffaSHans Petter Selasky
261*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) {
262*d6b92ffaSHans Petter Selasky if (key < p_item->key) {
263*d6b92ffaSHans Petter Selasky p_item_found = p_item;
264*d6b92ffaSHans Petter Selasky p_item = p_item->p_left;
265*d6b92ffaSHans Petter Selasky } else {
266*d6b92ffaSHans Petter Selasky p_item = p_item->p_right;
267*d6b92ffaSHans Petter Selasky }
268*d6b92ffaSHans Petter Selasky }
269*d6b92ffaSHans Petter Selasky
270*d6b92ffaSHans Petter Selasky return (p_item_found);
271*d6b92ffaSHans Petter Selasky }
272*d6b92ffaSHans Petter Selasky
cl_qmap_apply_func(IN const cl_qmap_t * const p_map,IN cl_pfn_qmap_apply_t pfn_func,IN const void * const context)273*d6b92ffaSHans Petter Selasky void cl_qmap_apply_func(IN const cl_qmap_t * const p_map,
274*d6b92ffaSHans Petter Selasky IN cl_pfn_qmap_apply_t pfn_func,
275*d6b92ffaSHans Petter Selasky IN const void *const context)
276*d6b92ffaSHans Petter Selasky {
277*d6b92ffaSHans Petter Selasky cl_map_item_t *p_map_item;
278*d6b92ffaSHans Petter Selasky
279*d6b92ffaSHans Petter Selasky /* Note that context can have any arbitrary value. */
280*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
281*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
282*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_func);
283*d6b92ffaSHans Petter Selasky
284*d6b92ffaSHans Petter Selasky p_map_item = cl_qmap_head(p_map);
285*d6b92ffaSHans Petter Selasky while (p_map_item != cl_qmap_end(p_map)) {
286*d6b92ffaSHans Petter Selasky pfn_func(p_map_item, (void *)context);
287*d6b92ffaSHans Petter Selasky p_map_item = cl_qmap_next(p_map_item);
288*d6b92ffaSHans Petter Selasky }
289*d6b92ffaSHans Petter Selasky }
290*d6b92ffaSHans Petter Selasky
291*d6b92ffaSHans Petter Selasky /*
292*d6b92ffaSHans Petter Selasky * Balance a tree starting at a given item back to the root.
293*d6b92ffaSHans Petter Selasky */
__cl_map_ins_bal(IN cl_qmap_t * const p_map,IN cl_map_item_t * p_item)294*d6b92ffaSHans Petter Selasky static void __cl_map_ins_bal(IN cl_qmap_t * const p_map,
295*d6b92ffaSHans Petter Selasky IN cl_map_item_t * p_item)
296*d6b92ffaSHans Petter Selasky {
297*d6b92ffaSHans Petter Selasky cl_map_item_t *p_grand_uncle;
298*d6b92ffaSHans Petter Selasky
299*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
300*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
301*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item != &p_map->root);
302*d6b92ffaSHans Petter Selasky
303*d6b92ffaSHans Petter Selasky while (p_item->p_up->color == CL_MAP_RED) {
304*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item->p_up)) {
305*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_right;
306*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle);
307*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) {
308*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK;
309*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
310*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
311*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up;
312*d6b92ffaSHans Petter Selasky continue;
313*d6b92ffaSHans Petter Selasky }
314*d6b92ffaSHans Petter Selasky
315*d6b92ffaSHans Petter Selasky if (!__cl_map_is_left_child(p_item)) {
316*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
317*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item);
318*d6b92ffaSHans Petter Selasky }
319*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
320*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
321*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up->p_up);
322*d6b92ffaSHans Petter Selasky } else {
323*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_left;
324*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle);
325*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) {
326*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK;
327*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
328*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
329*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up;
330*d6b92ffaSHans Petter Selasky continue;
331*d6b92ffaSHans Petter Selasky }
332*d6b92ffaSHans Petter Selasky
333*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item)) {
334*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
335*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item);
336*d6b92ffaSHans Petter Selasky }
337*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
338*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
339*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up->p_up);
340*d6b92ffaSHans Petter Selasky }
341*d6b92ffaSHans Petter Selasky }
342*d6b92ffaSHans Petter Selasky }
343*d6b92ffaSHans Petter Selasky
cl_qmap_insert(IN cl_qmap_t * const p_map,IN const uint64_t key,IN cl_map_item_t * const p_item)344*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_insert(IN cl_qmap_t * const p_map,
345*d6b92ffaSHans Petter Selasky IN const uint64_t key,
346*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item)
347*d6b92ffaSHans Petter Selasky {
348*d6b92ffaSHans Petter Selasky cl_map_item_t *p_insert_at, *p_comp_item;
349*d6b92ffaSHans Petter Selasky
350*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
351*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
352*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
353*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.p_up == &p_map->root);
354*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.color != CL_MAP_RED);
355*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED);
356*d6b92ffaSHans Petter Selasky
357*d6b92ffaSHans Petter Selasky p_item->p_left = &p_map->nil;
358*d6b92ffaSHans Petter Selasky p_item->p_right = &p_map->nil;
359*d6b92ffaSHans Petter Selasky p_item->key = key;
360*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_RED;
361*d6b92ffaSHans Petter Selasky
362*d6b92ffaSHans Petter Selasky /* Find the insertion location. */
363*d6b92ffaSHans Petter Selasky p_insert_at = &p_map->root;
364*d6b92ffaSHans Petter Selasky p_comp_item = __cl_map_root(p_map);
365*d6b92ffaSHans Petter Selasky
366*d6b92ffaSHans Petter Selasky while (p_comp_item != &p_map->nil) {
367*d6b92ffaSHans Petter Selasky p_insert_at = p_comp_item;
368*d6b92ffaSHans Petter Selasky
369*d6b92ffaSHans Petter Selasky if (key == p_insert_at->key)
370*d6b92ffaSHans Petter Selasky return (p_insert_at);
371*d6b92ffaSHans Petter Selasky
372*d6b92ffaSHans Petter Selasky /* Traverse the tree until the correct insertion point is found. */
373*d6b92ffaSHans Petter Selasky if (key < p_insert_at->key)
374*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_left;
375*d6b92ffaSHans Petter Selasky else
376*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_right;
377*d6b92ffaSHans Petter Selasky }
378*d6b92ffaSHans Petter Selasky
379*d6b92ffaSHans Petter Selasky CL_ASSERT(p_insert_at != &p_map->nil);
380*d6b92ffaSHans Petter Selasky CL_ASSERT(p_comp_item == &p_map->nil);
381*d6b92ffaSHans Petter Selasky /* Insert the item. */
382*d6b92ffaSHans Petter Selasky if (p_insert_at == &p_map->root) {
383*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item;
384*d6b92ffaSHans Petter Selasky /*
385*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
386*d6b92ffaSHans Petter Selasky * the existing item.
387*d6b92ffaSHans Petter Selasky */
388*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_map->nil.pool_item.list_item,
389*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
390*d6b92ffaSHans Petter Selasky } else if (key < p_insert_at->key) {
391*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item;
392*d6b92ffaSHans Petter Selasky /*
393*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
394*d6b92ffaSHans Petter Selasky * the existing item.
395*d6b92ffaSHans Petter Selasky */
396*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_insert_at->pool_item.list_item,
397*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
398*d6b92ffaSHans Petter Selasky } else {
399*d6b92ffaSHans Petter Selasky p_insert_at->p_right = p_item;
400*d6b92ffaSHans Petter Selasky /*
401*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
402*d6b92ffaSHans Petter Selasky * the existing item.
403*d6b92ffaSHans Petter Selasky */
404*d6b92ffaSHans Petter Selasky __cl_primitive_insert(p_insert_at->pool_item.list_item.p_next,
405*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
406*d6b92ffaSHans Petter Selasky }
407*d6b92ffaSHans Petter Selasky /* Increase the count. */
408*d6b92ffaSHans Petter Selasky p_map->count++;
409*d6b92ffaSHans Petter Selasky
410*d6b92ffaSHans Petter Selasky p_item->p_up = p_insert_at;
411*d6b92ffaSHans Petter Selasky
412*d6b92ffaSHans Petter Selasky /*
413*d6b92ffaSHans Petter Selasky * We have added depth to this section of the tree.
414*d6b92ffaSHans Petter Selasky * Rebalance as necessary as we retrace our path through the tree
415*d6b92ffaSHans Petter Selasky * and update colors.
416*d6b92ffaSHans Petter Selasky */
417*d6b92ffaSHans Petter Selasky __cl_map_ins_bal(p_map, p_item);
418*d6b92ffaSHans Petter Selasky
419*d6b92ffaSHans Petter Selasky __cl_map_root(p_map)->color = CL_MAP_BLACK;
420*d6b92ffaSHans Petter Selasky
421*d6b92ffaSHans Petter Selasky /*
422*d6b92ffaSHans Petter Selasky * Note that it is not necessary to re-color the nil node black because all
423*d6b92ffaSHans Petter Selasky * red color assignments are made via the p_up pointer, and nil is never
424*d6b92ffaSHans Petter Selasky * set as the value of a p_up pointer.
425*d6b92ffaSHans Petter Selasky */
426*d6b92ffaSHans Petter Selasky
427*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
428*d6b92ffaSHans Petter Selasky /* Set the pointer to the map in the map item for consistency checking. */
429*d6b92ffaSHans Petter Selasky p_item->p_map = p_map;
430*d6b92ffaSHans Petter Selasky #endif
431*d6b92ffaSHans Petter Selasky
432*d6b92ffaSHans Petter Selasky return (p_item);
433*d6b92ffaSHans Petter Selasky }
434*d6b92ffaSHans Petter Selasky
__cl_map_del_bal(IN cl_qmap_t * const p_map,IN cl_map_item_t * p_item)435*d6b92ffaSHans Petter Selasky static void __cl_map_del_bal(IN cl_qmap_t * const p_map,
436*d6b92ffaSHans Petter Selasky IN cl_map_item_t * p_item)
437*d6b92ffaSHans Petter Selasky {
438*d6b92ffaSHans Petter Selasky cl_map_item_t *p_uncle;
439*d6b92ffaSHans Petter Selasky
440*d6b92ffaSHans Petter Selasky while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) {
441*d6b92ffaSHans Petter Selasky if (__cl_map_is_left_child(p_item)) {
442*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
443*d6b92ffaSHans Petter Selasky
444*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) {
445*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK;
446*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED;
447*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up);
448*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
449*d6b92ffaSHans Petter Selasky }
450*d6b92ffaSHans Petter Selasky
451*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) {
452*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) {
453*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
454*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
455*d6b92ffaSHans Petter Selasky continue;
456*d6b92ffaSHans Petter Selasky }
457*d6b92ffaSHans Petter Selasky
458*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK;
459*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
460*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_uncle);
461*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
462*d6b92ffaSHans Petter Selasky }
463*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color;
464*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
465*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK;
466*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_item->p_up);
467*d6b92ffaSHans Petter Selasky break;
468*d6b92ffaSHans Petter Selasky } else {
469*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
470*d6b92ffaSHans Petter Selasky
471*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) {
472*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK;
473*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED;
474*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up);
475*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
476*d6b92ffaSHans Petter Selasky }
477*d6b92ffaSHans Petter Selasky
478*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) {
479*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) {
480*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
481*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
482*d6b92ffaSHans Petter Selasky continue;
483*d6b92ffaSHans Petter Selasky }
484*d6b92ffaSHans Petter Selasky
485*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK;
486*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
487*d6b92ffaSHans Petter Selasky __cl_map_rot_left(p_map, p_uncle);
488*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
489*d6b92ffaSHans Petter Selasky }
490*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color;
491*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
492*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK;
493*d6b92ffaSHans Petter Selasky __cl_map_rot_right(p_map, p_item->p_up);
494*d6b92ffaSHans Petter Selasky break;
495*d6b92ffaSHans Petter Selasky }
496*d6b92ffaSHans Petter Selasky }
497*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_BLACK;
498*d6b92ffaSHans Petter Selasky }
499*d6b92ffaSHans Petter Selasky
cl_qmap_remove_item(IN cl_qmap_t * const p_map,IN cl_map_item_t * const p_item)500*d6b92ffaSHans Petter Selasky void cl_qmap_remove_item(IN cl_qmap_t * const p_map,
501*d6b92ffaSHans Petter Selasky IN cl_map_item_t * const p_item)
502*d6b92ffaSHans Petter Selasky {
503*d6b92ffaSHans Petter Selasky cl_map_item_t *p_child, *p_del_item;
504*d6b92ffaSHans Petter Selasky
505*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
506*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
507*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
508*d6b92ffaSHans Petter Selasky
509*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(p_map))
510*d6b92ffaSHans Petter Selasky return;
511*d6b92ffaSHans Petter Selasky
512*d6b92ffaSHans Petter Selasky /* must be checked after comparing to cl_qmap_end, since
513*d6b92ffaSHans Petter Selasky the end is not a valid item. */
514*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_map == p_map);
515*d6b92ffaSHans Petter Selasky
516*d6b92ffaSHans Petter Selasky if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) {
517*d6b92ffaSHans Petter Selasky /* The item being removed has children on at most on side. */
518*d6b92ffaSHans Petter Selasky p_del_item = p_item;
519*d6b92ffaSHans Petter Selasky } else {
520*d6b92ffaSHans Petter Selasky /*
521*d6b92ffaSHans Petter Selasky * The item being removed has children on both side.
522*d6b92ffaSHans Petter Selasky * We select the item that will replace it. After removing
523*d6b92ffaSHans Petter Selasky * the substitute item and rebalancing, the tree will have the
524*d6b92ffaSHans Petter Selasky * correct topology. Exchanging the substitute for the item
525*d6b92ffaSHans Petter Selasky * will finalize the removal.
526*d6b92ffaSHans Petter Selasky */
527*d6b92ffaSHans Petter Selasky p_del_item = cl_qmap_next(p_item);
528*d6b92ffaSHans Petter Selasky CL_ASSERT(p_del_item != &p_map->nil);
529*d6b92ffaSHans Petter Selasky }
530*d6b92ffaSHans Petter Selasky
531*d6b92ffaSHans Petter Selasky /* Remove the item from the list. */
532*d6b92ffaSHans Petter Selasky __cl_primitive_remove(&p_item->pool_item.list_item);
533*d6b92ffaSHans Petter Selasky /* Decrement the item count. */
534*d6b92ffaSHans Petter Selasky p_map->count--;
535*d6b92ffaSHans Petter Selasky
536*d6b92ffaSHans Petter Selasky /* Get the pointer to the new root's child, if any. */
537*d6b92ffaSHans Petter Selasky if (p_del_item->p_left != &p_map->nil)
538*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_left;
539*d6b92ffaSHans Petter Selasky else
540*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_right;
541*d6b92ffaSHans Petter Selasky
542*d6b92ffaSHans Petter Selasky /*
543*d6b92ffaSHans Petter Selasky * This assignment may modify the parent pointer of the nil node.
544*d6b92ffaSHans Petter Selasky * This is inconsequential.
545*d6b92ffaSHans Petter Selasky */
546*d6b92ffaSHans Petter Selasky p_child->p_up = p_del_item->p_up;
547*d6b92ffaSHans Petter Selasky (*__cl_map_get_parent_ptr_to_item(p_del_item)) = p_child;
548*d6b92ffaSHans Petter Selasky
549*d6b92ffaSHans Petter Selasky if (p_del_item->color != CL_MAP_RED)
550*d6b92ffaSHans Petter Selasky __cl_map_del_bal(p_map, p_child);
551*d6b92ffaSHans Petter Selasky
552*d6b92ffaSHans Petter Selasky /*
553*d6b92ffaSHans Petter Selasky * Note that the splicing done below does not need to occur before
554*d6b92ffaSHans Petter Selasky * the tree is balanced, since the actual topology changes are made by the
555*d6b92ffaSHans Petter Selasky * preceding code. The topology is preserved by the color assignment made
556*d6b92ffaSHans Petter Selasky * below (reader should be reminded that p_del_item == p_item in some cases).
557*d6b92ffaSHans Petter Selasky */
558*d6b92ffaSHans Petter Selasky if (p_del_item != p_item) {
559*d6b92ffaSHans Petter Selasky /*
560*d6b92ffaSHans Petter Selasky * Finalize the removal of the specified item by exchanging it with
561*d6b92ffaSHans Petter Selasky * the substitute which we removed above.
562*d6b92ffaSHans Petter Selasky */
563*d6b92ffaSHans Petter Selasky p_del_item->p_up = p_item->p_up;
564*d6b92ffaSHans Petter Selasky p_del_item->p_left = p_item->p_left;
565*d6b92ffaSHans Petter Selasky p_del_item->p_right = p_item->p_right;
566*d6b92ffaSHans Petter Selasky (*__cl_map_get_parent_ptr_to_item(p_item)) = p_del_item;
567*d6b92ffaSHans Petter Selasky p_item->p_right->p_up = p_del_item;
568*d6b92ffaSHans Petter Selasky p_item->p_left->p_up = p_del_item;
569*d6b92ffaSHans Petter Selasky p_del_item->color = p_item->color;
570*d6b92ffaSHans Petter Selasky }
571*d6b92ffaSHans Petter Selasky
572*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED);
573*d6b92ffaSHans Petter Selasky
574*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
575*d6b92ffaSHans Petter Selasky /* Clear the pointer to the map since the item has been removed. */
576*d6b92ffaSHans Petter Selasky p_item->p_map = NULL;
577*d6b92ffaSHans Petter Selasky #endif
578*d6b92ffaSHans Petter Selasky }
579*d6b92ffaSHans Petter Selasky
cl_qmap_remove(IN cl_qmap_t * const p_map,IN const uint64_t key)580*d6b92ffaSHans Petter Selasky cl_map_item_t *cl_qmap_remove(IN cl_qmap_t * const p_map, IN const uint64_t key)
581*d6b92ffaSHans Petter Selasky {
582*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
583*d6b92ffaSHans Petter Selasky
584*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
585*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
586*d6b92ffaSHans Petter Selasky
587*d6b92ffaSHans Petter Selasky /* Seek the node with the specified key */
588*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get(p_map, key);
589*d6b92ffaSHans Petter Selasky
590*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_map, p_item);
591*d6b92ffaSHans Petter Selasky
592*d6b92ffaSHans Petter Selasky return (p_item);
593*d6b92ffaSHans Petter Selasky }
594*d6b92ffaSHans Petter Selasky
cl_qmap_merge(OUT cl_qmap_t * const p_dest_map,IN OUT cl_qmap_t * const p_src_map)595*d6b92ffaSHans Petter Selasky void cl_qmap_merge(OUT cl_qmap_t * const p_dest_map,
596*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_src_map)
597*d6b92ffaSHans Petter Selasky {
598*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item, *p_item2, *p_next;
599*d6b92ffaSHans Petter Selasky
600*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map);
601*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map);
602*d6b92ffaSHans Petter Selasky
603*d6b92ffaSHans Petter Selasky p_item = cl_qmap_head(p_src_map);
604*d6b92ffaSHans Petter Selasky
605*d6b92ffaSHans Petter Selasky while (p_item != cl_qmap_end(p_src_map)) {
606*d6b92ffaSHans Petter Selasky p_next = cl_qmap_next(p_item);
607*d6b92ffaSHans Petter Selasky
608*d6b92ffaSHans Petter Selasky /* Remove the item from its current map. */
609*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_src_map, p_item);
610*d6b92ffaSHans Petter Selasky /* Insert the item into the destination map. */
611*d6b92ffaSHans Petter Selasky p_item2 =
612*d6b92ffaSHans Petter Selasky cl_qmap_insert(p_dest_map, cl_qmap_key(p_item), p_item);
613*d6b92ffaSHans Petter Selasky /* Check that the item was successfully inserted. */
614*d6b92ffaSHans Petter Selasky if (p_item2 != p_item) {
615*d6b92ffaSHans Petter Selasky /* Put the item in back in the source map. */
616*d6b92ffaSHans Petter Selasky p_item2 =
617*d6b92ffaSHans Petter Selasky cl_qmap_insert(p_src_map, cl_qmap_key(p_item),
618*d6b92ffaSHans Petter Selasky p_item);
619*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item2 == p_item);
620*d6b92ffaSHans Petter Selasky }
621*d6b92ffaSHans Petter Selasky p_item = p_next;
622*d6b92ffaSHans Petter Selasky }
623*d6b92ffaSHans Petter Selasky }
624*d6b92ffaSHans Petter Selasky
__cl_qmap_delta_move(IN OUT cl_qmap_t * const p_dest,IN OUT cl_qmap_t * const p_src,IN OUT cl_map_item_t ** const pp_item)625*d6b92ffaSHans Petter Selasky static void __cl_qmap_delta_move(IN OUT cl_qmap_t * const p_dest,
626*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_src,
627*d6b92ffaSHans Petter Selasky IN OUT cl_map_item_t ** const pp_item)
628*d6b92ffaSHans Petter Selasky {
629*d6b92ffaSHans Petter Selasky cl_map_item_t __attribute__((__unused__)) *p_temp;
630*d6b92ffaSHans Petter Selasky cl_map_item_t *p_next;
631*d6b92ffaSHans Petter Selasky
632*d6b92ffaSHans Petter Selasky /*
633*d6b92ffaSHans Petter Selasky * Get the next item so that we can ensure that pp_item points to
634*d6b92ffaSHans Petter Selasky * a valid item upon return from the function.
635*d6b92ffaSHans Petter Selasky */
636*d6b92ffaSHans Petter Selasky p_next = cl_qmap_next(*pp_item);
637*d6b92ffaSHans Petter Selasky /* Move the old item from its current map the the old map. */
638*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(p_src, *pp_item);
639*d6b92ffaSHans Petter Selasky p_temp = cl_qmap_insert(p_dest, cl_qmap_key(*pp_item), *pp_item);
640*d6b92ffaSHans Petter Selasky /* We should never have duplicates. */
641*d6b92ffaSHans Petter Selasky CL_ASSERT(p_temp == *pp_item);
642*d6b92ffaSHans Petter Selasky /* Point pp_item to a valid item in the source map. */
643*d6b92ffaSHans Petter Selasky (*pp_item) = p_next;
644*d6b92ffaSHans Petter Selasky }
645*d6b92ffaSHans Petter Selasky
cl_qmap_delta(IN OUT cl_qmap_t * const p_map1,IN OUT cl_qmap_t * const p_map2,OUT cl_qmap_t * const p_new,OUT cl_qmap_t * const p_old)646*d6b92ffaSHans Petter Selasky void cl_qmap_delta(IN OUT cl_qmap_t * const p_map1,
647*d6b92ffaSHans Petter Selasky IN OUT cl_qmap_t * const p_map2,
648*d6b92ffaSHans Petter Selasky OUT cl_qmap_t * const p_new, OUT cl_qmap_t * const p_old)
649*d6b92ffaSHans Petter Selasky {
650*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item1, *p_item2;
651*d6b92ffaSHans Petter Selasky uint64_t key1, key2;
652*d6b92ffaSHans Petter Selasky
653*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1);
654*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2);
655*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new);
656*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old);
657*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_qmap_empty(p_new));
658*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_qmap_empty(p_old));
659*d6b92ffaSHans Petter Selasky
660*d6b92ffaSHans Petter Selasky p_item1 = cl_qmap_head(p_map1);
661*d6b92ffaSHans Petter Selasky p_item2 = cl_qmap_head(p_map2);
662*d6b92ffaSHans Petter Selasky
663*d6b92ffaSHans Petter Selasky while (p_item1 != cl_qmap_end(p_map1) && p_item2 != cl_qmap_end(p_map2)) {
664*d6b92ffaSHans Petter Selasky key1 = cl_qmap_key(p_item1);
665*d6b92ffaSHans Petter Selasky key2 = cl_qmap_key(p_item2);
666*d6b92ffaSHans Petter Selasky if (key1 < key2) {
667*d6b92ffaSHans Petter Selasky /* We found an old item. */
668*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_old, p_map1, &p_item1);
669*d6b92ffaSHans Petter Selasky } else if (key1 > key2) {
670*d6b92ffaSHans Petter Selasky /* We found a new item. */
671*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_new, p_map2, &p_item2);
672*d6b92ffaSHans Petter Selasky } else {
673*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */
674*d6b92ffaSHans Petter Selasky p_item1 = cl_qmap_next(p_item1);
675*d6b92ffaSHans Petter Selasky p_item2 = cl_qmap_next(p_item2);
676*d6b92ffaSHans Petter Selasky }
677*d6b92ffaSHans Petter Selasky }
678*d6b92ffaSHans Petter Selasky
679*d6b92ffaSHans Petter Selasky /* Process the remainder if the end of either source map was reached. */
680*d6b92ffaSHans Petter Selasky while (p_item2 != cl_qmap_end(p_map2))
681*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_new, p_map2, &p_item2);
682*d6b92ffaSHans Petter Selasky
683*d6b92ffaSHans Petter Selasky while (p_item1 != cl_qmap_end(p_map1))
684*d6b92ffaSHans Petter Selasky __cl_qmap_delta_move(p_old, p_map1, &p_item1);
685*d6b92ffaSHans Petter Selasky }
686*d6b92ffaSHans Petter Selasky
687*d6b92ffaSHans Petter Selasky /******************************************************************************
688*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF MAP
689*d6b92ffaSHans Petter Selasky ******************************************************************************/
690*d6b92ffaSHans Petter Selasky
691*d6b92ffaSHans Petter Selasky #define MAP_GROW_SIZE 32
692*d6b92ffaSHans Petter Selasky
cl_map_construct(IN cl_map_t * const p_map)693*d6b92ffaSHans Petter Selasky void cl_map_construct(IN cl_map_t * const p_map)
694*d6b92ffaSHans Petter Selasky {
695*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
696*d6b92ffaSHans Petter Selasky
697*d6b92ffaSHans Petter Selasky cl_qpool_construct(&p_map->pool);
698*d6b92ffaSHans Petter Selasky }
699*d6b92ffaSHans Petter Selasky
cl_map_init(IN cl_map_t * const p_map,IN const uint32_t min_items)700*d6b92ffaSHans Petter Selasky cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items)
701*d6b92ffaSHans Petter Selasky {
702*d6b92ffaSHans Petter Selasky uint32_t grow_size;
703*d6b92ffaSHans Petter Selasky
704*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
705*d6b92ffaSHans Petter Selasky
706*d6b92ffaSHans Petter Selasky cl_qmap_init(&p_map->qmap);
707*d6b92ffaSHans Petter Selasky
708*d6b92ffaSHans Petter Selasky /*
709*d6b92ffaSHans Petter Selasky * We will grow by min_items/8 items at a time, with a minimum of
710*d6b92ffaSHans Petter Selasky * MAP_GROW_SIZE.
711*d6b92ffaSHans Petter Selasky */
712*d6b92ffaSHans Petter Selasky grow_size = min_items >> 3;
713*d6b92ffaSHans Petter Selasky if (grow_size < MAP_GROW_SIZE)
714*d6b92ffaSHans Petter Selasky grow_size = MAP_GROW_SIZE;
715*d6b92ffaSHans Petter Selasky
716*d6b92ffaSHans Petter Selasky return (cl_qpool_init(&p_map->pool, min_items, 0, grow_size,
717*d6b92ffaSHans Petter Selasky sizeof(cl_map_obj_t), NULL, NULL, NULL));
718*d6b92ffaSHans Petter Selasky }
719*d6b92ffaSHans Petter Selasky
cl_map_destroy(IN cl_map_t * const p_map)720*d6b92ffaSHans Petter Selasky void cl_map_destroy(IN cl_map_t * const p_map)
721*d6b92ffaSHans Petter Selasky {
722*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
723*d6b92ffaSHans Petter Selasky
724*d6b92ffaSHans Petter Selasky cl_qpool_destroy(&p_map->pool);
725*d6b92ffaSHans Petter Selasky }
726*d6b92ffaSHans Petter Selasky
cl_map_insert(IN cl_map_t * const p_map,IN const uint64_t key,IN const void * const p_object)727*d6b92ffaSHans Petter Selasky void *cl_map_insert(IN cl_map_t * const p_map,
728*d6b92ffaSHans Petter Selasky IN const uint64_t key, IN const void *const p_object)
729*d6b92ffaSHans Petter Selasky {
730*d6b92ffaSHans Petter Selasky cl_map_obj_t *p_map_obj, *p_obj_at_key;
731*d6b92ffaSHans Petter Selasky
732*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
733*d6b92ffaSHans Petter Selasky
734*d6b92ffaSHans Petter Selasky p_map_obj = (cl_map_obj_t *) cl_qpool_get(&p_map->pool);
735*d6b92ffaSHans Petter Selasky
736*d6b92ffaSHans Petter Selasky if (!p_map_obj)
737*d6b92ffaSHans Petter Selasky return (NULL);
738*d6b92ffaSHans Petter Selasky
739*d6b92ffaSHans Petter Selasky cl_qmap_set_obj(p_map_obj, p_object);
740*d6b92ffaSHans Petter Selasky
741*d6b92ffaSHans Petter Selasky p_obj_at_key =
742*d6b92ffaSHans Petter Selasky (cl_map_obj_t *) cl_qmap_insert(&p_map->qmap, key,
743*d6b92ffaSHans Petter Selasky &p_map_obj->item);
744*d6b92ffaSHans Petter Selasky
745*d6b92ffaSHans Petter Selasky /* Return the item to the pool if insertion failed. */
746*d6b92ffaSHans Petter Selasky if (p_obj_at_key != p_map_obj)
747*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_map_obj->item.pool_item);
748*d6b92ffaSHans Petter Selasky
749*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(p_obj_at_key));
750*d6b92ffaSHans Petter Selasky }
751*d6b92ffaSHans Petter Selasky
cl_map_get(IN const cl_map_t * const p_map,IN const uint64_t key)752*d6b92ffaSHans Petter Selasky void *cl_map_get(IN const cl_map_t * const p_map, IN const uint64_t key)
753*d6b92ffaSHans Petter Selasky {
754*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
755*d6b92ffaSHans Petter Selasky
756*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
757*d6b92ffaSHans Petter Selasky
758*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get(&p_map->qmap, key);
759*d6b92ffaSHans Petter Selasky
760*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap))
761*d6b92ffaSHans Petter Selasky return (NULL);
762*d6b92ffaSHans Petter Selasky
763*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item)));
764*d6b92ffaSHans Petter Selasky }
765*d6b92ffaSHans Petter Selasky
cl_map_get_next(IN const cl_map_t * const p_map,IN const uint64_t key)766*d6b92ffaSHans Petter Selasky void *cl_map_get_next(IN const cl_map_t * const p_map, IN const uint64_t key)
767*d6b92ffaSHans Petter Selasky {
768*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
769*d6b92ffaSHans Petter Selasky
770*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
771*d6b92ffaSHans Petter Selasky
772*d6b92ffaSHans Petter Selasky p_item = cl_qmap_get_next(&p_map->qmap, key);
773*d6b92ffaSHans Petter Selasky
774*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap))
775*d6b92ffaSHans Petter Selasky return (NULL);
776*d6b92ffaSHans Petter Selasky
777*d6b92ffaSHans Petter Selasky return (cl_qmap_obj(PARENT_STRUCT(p_item, cl_map_obj_t, item)));
778*d6b92ffaSHans Petter Selasky }
779*d6b92ffaSHans Petter Selasky
cl_map_remove_item(IN cl_map_t * const p_map,IN const cl_map_iterator_t itor)780*d6b92ffaSHans Petter Selasky void cl_map_remove_item(IN cl_map_t * const p_map,
781*d6b92ffaSHans Petter Selasky IN const cl_map_iterator_t itor)
782*d6b92ffaSHans Petter Selasky {
783*d6b92ffaSHans Petter Selasky CL_ASSERT(itor->p_map == &p_map->qmap);
784*d6b92ffaSHans Petter Selasky
785*d6b92ffaSHans Petter Selasky if (itor == cl_map_end(p_map))
786*d6b92ffaSHans Petter Selasky return;
787*d6b92ffaSHans Petter Selasky
788*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, (cl_map_item_t *) itor);
789*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &((cl_map_item_t *) itor)->pool_item);
790*d6b92ffaSHans Petter Selasky }
791*d6b92ffaSHans Petter Selasky
cl_map_remove(IN cl_map_t * const p_map,IN const uint64_t key)792*d6b92ffaSHans Petter Selasky void *cl_map_remove(IN cl_map_t * const p_map, IN const uint64_t key)
793*d6b92ffaSHans Petter Selasky {
794*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
795*d6b92ffaSHans Petter Selasky void *p_obj;
796*d6b92ffaSHans Petter Selasky
797*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
798*d6b92ffaSHans Petter Selasky
799*d6b92ffaSHans Petter Selasky p_item = cl_qmap_remove(&p_map->qmap, key);
800*d6b92ffaSHans Petter Selasky
801*d6b92ffaSHans Petter Selasky if (p_item == cl_qmap_end(&p_map->qmap))
802*d6b92ffaSHans Petter Selasky return (NULL);
803*d6b92ffaSHans Petter Selasky
804*d6b92ffaSHans Petter Selasky p_obj = cl_qmap_obj((cl_map_obj_t *) p_item);
805*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item);
806*d6b92ffaSHans Petter Selasky
807*d6b92ffaSHans Petter Selasky return (p_obj);
808*d6b92ffaSHans Petter Selasky }
809*d6b92ffaSHans Petter Selasky
cl_map_remove_all(IN cl_map_t * const p_map)810*d6b92ffaSHans Petter Selasky void cl_map_remove_all(IN cl_map_t * const p_map)
811*d6b92ffaSHans Petter Selasky {
812*d6b92ffaSHans Petter Selasky cl_map_item_t *p_item;
813*d6b92ffaSHans Petter Selasky
814*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
815*d6b92ffaSHans Petter Selasky
816*d6b92ffaSHans Petter Selasky /* Return all map items to the pool. */
817*d6b92ffaSHans Petter Selasky while (!cl_is_qmap_empty(&p_map->qmap)) {
818*d6b92ffaSHans Petter Selasky p_item = cl_qmap_head(&p_map->qmap);
819*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, p_item);
820*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item);
821*d6b92ffaSHans Petter Selasky
822*d6b92ffaSHans Petter Selasky if (!cl_is_qmap_empty(&p_map->qmap)) {
823*d6b92ffaSHans Petter Selasky p_item = cl_qmap_tail(&p_map->qmap);
824*d6b92ffaSHans Petter Selasky cl_qmap_remove_item(&p_map->qmap, p_item);
825*d6b92ffaSHans Petter Selasky cl_qpool_put(&p_map->pool, &p_item->pool_item);
826*d6b92ffaSHans Petter Selasky }
827*d6b92ffaSHans Petter Selasky }
828*d6b92ffaSHans Petter Selasky }
829*d6b92ffaSHans Petter Selasky
cl_map_merge(OUT cl_map_t * const p_dest_map,IN OUT cl_map_t * const p_src_map)830*d6b92ffaSHans Petter Selasky cl_status_t cl_map_merge(OUT cl_map_t * const p_dest_map,
831*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_src_map)
832*d6b92ffaSHans Petter Selasky {
833*d6b92ffaSHans Petter Selasky cl_status_t status = CL_SUCCESS;
834*d6b92ffaSHans Petter Selasky cl_map_iterator_t itor, next;
835*d6b92ffaSHans Petter Selasky uint64_t key;
836*d6b92ffaSHans Petter Selasky void *p_obj, *p_obj2;
837*d6b92ffaSHans Petter Selasky
838*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map);
839*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map);
840*d6b92ffaSHans Petter Selasky
841*d6b92ffaSHans Petter Selasky itor = cl_map_head(p_src_map);
842*d6b92ffaSHans Petter Selasky while (itor != cl_map_end(p_src_map)) {
843*d6b92ffaSHans Petter Selasky next = cl_map_next(itor);
844*d6b92ffaSHans Petter Selasky
845*d6b92ffaSHans Petter Selasky p_obj = cl_map_obj(itor);
846*d6b92ffaSHans Petter Selasky key = cl_map_key(itor);
847*d6b92ffaSHans Petter Selasky
848*d6b92ffaSHans Petter Selasky cl_map_remove_item(p_src_map, itor);
849*d6b92ffaSHans Petter Selasky
850*d6b92ffaSHans Petter Selasky /* Insert the object into the destination map. */
851*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_dest_map, key, p_obj);
852*d6b92ffaSHans Petter Selasky /* Trap for failure. */
853*d6b92ffaSHans Petter Selasky if (p_obj != p_obj2) {
854*d6b92ffaSHans Petter Selasky if (!p_obj2)
855*d6b92ffaSHans Petter Selasky status = CL_INSUFFICIENT_MEMORY;
856*d6b92ffaSHans Petter Selasky /* Put the object back in the source map. This must succeed. */
857*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_src_map, key, p_obj);
858*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj == p_obj2);
859*d6b92ffaSHans Petter Selasky /* If the failure was due to insufficient memory, return. */
860*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS)
861*d6b92ffaSHans Petter Selasky return (status);
862*d6b92ffaSHans Petter Selasky }
863*d6b92ffaSHans Petter Selasky itor = next;
864*d6b92ffaSHans Petter Selasky }
865*d6b92ffaSHans Petter Selasky
866*d6b92ffaSHans Petter Selasky return (CL_SUCCESS);
867*d6b92ffaSHans Petter Selasky }
868*d6b92ffaSHans Petter Selasky
__cl_map_revert(IN OUT cl_map_t * const p_map1,IN OUT cl_map_t * const p_map2,IN OUT cl_map_t * const p_new,IN OUT cl_map_t * const p_old)869*d6b92ffaSHans Petter Selasky static void __cl_map_revert(IN OUT cl_map_t * const p_map1,
870*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_map2,
871*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_new,
872*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_old)
873*d6b92ffaSHans Petter Selasky {
874*d6b92ffaSHans Petter Selasky cl_status_t __attribute__((__unused__)) status;
875*d6b92ffaSHans Petter Selasky
876*d6b92ffaSHans Petter Selasky /* Restore the initial state. */
877*d6b92ffaSHans Petter Selasky status = cl_map_merge(p_map1, p_old);
878*d6b92ffaSHans Petter Selasky CL_ASSERT(status == CL_SUCCESS);
879*d6b92ffaSHans Petter Selasky status = cl_map_merge(p_map2, p_new);
880*d6b92ffaSHans Petter Selasky CL_ASSERT(status == CL_SUCCESS);
881*d6b92ffaSHans Petter Selasky }
882*d6b92ffaSHans Petter Selasky
__cl_map_delta_move(OUT cl_map_t * const p_dest,IN OUT cl_map_t * const p_src,IN OUT cl_map_iterator_t * const p_itor)883*d6b92ffaSHans Petter Selasky static cl_status_t __cl_map_delta_move(OUT cl_map_t * const p_dest,
884*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_src,
885*d6b92ffaSHans Petter Selasky IN OUT cl_map_iterator_t * const p_itor)
886*d6b92ffaSHans Petter Selasky {
887*d6b92ffaSHans Petter Selasky cl_map_iterator_t next;
888*d6b92ffaSHans Petter Selasky void *p_obj, *p_obj2;
889*d6b92ffaSHans Petter Selasky uint64_t key;
890*d6b92ffaSHans Petter Selasky
891*d6b92ffaSHans Petter Selasky /* Get a valid iterator so we can continue the loop. */
892*d6b92ffaSHans Petter Selasky next = cl_map_next(*p_itor);
893*d6b92ffaSHans Petter Selasky /* Get the pointer to the object for insertion. */
894*d6b92ffaSHans Petter Selasky p_obj = cl_map_obj(*p_itor);
895*d6b92ffaSHans Petter Selasky /* Get the key for the object. */
896*d6b92ffaSHans Petter Selasky key = cl_map_key(*p_itor);
897*d6b92ffaSHans Petter Selasky /* Move the object. */
898*d6b92ffaSHans Petter Selasky cl_map_remove_item(p_src, *p_itor);
899*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_dest, key, p_obj);
900*d6b92ffaSHans Petter Selasky /* Check for failure. We should never get a duplicate. */
901*d6b92ffaSHans Petter Selasky if (!p_obj2) {
902*d6b92ffaSHans Petter Selasky p_obj2 = cl_map_insert(p_src, key, p_obj);
903*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj2 == p_obj);
904*d6b92ffaSHans Petter Selasky return (CL_INSUFFICIENT_MEMORY);
905*d6b92ffaSHans Petter Selasky }
906*d6b92ffaSHans Petter Selasky
907*d6b92ffaSHans Petter Selasky /* We should never get a duplicate */
908*d6b92ffaSHans Petter Selasky CL_ASSERT(p_obj == p_obj2);
909*d6b92ffaSHans Petter Selasky /* Update the iterator so that it is valid. */
910*d6b92ffaSHans Petter Selasky (*p_itor) = next;
911*d6b92ffaSHans Petter Selasky
912*d6b92ffaSHans Petter Selasky return (CL_SUCCESS);
913*d6b92ffaSHans Petter Selasky }
914*d6b92ffaSHans Petter Selasky
cl_map_delta(IN OUT cl_map_t * const p_map1,IN OUT cl_map_t * const p_map2,OUT cl_map_t * const p_new,OUT cl_map_t * const p_old)915*d6b92ffaSHans Petter Selasky cl_status_t cl_map_delta(IN OUT cl_map_t * const p_map1,
916*d6b92ffaSHans Petter Selasky IN OUT cl_map_t * const p_map2,
917*d6b92ffaSHans Petter Selasky OUT cl_map_t * const p_new, OUT cl_map_t * const p_old)
918*d6b92ffaSHans Petter Selasky {
919*d6b92ffaSHans Petter Selasky cl_map_iterator_t itor1, itor2;
920*d6b92ffaSHans Petter Selasky uint64_t key1, key2;
921*d6b92ffaSHans Petter Selasky cl_status_t status;
922*d6b92ffaSHans Petter Selasky
923*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1);
924*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2);
925*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new);
926*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old);
927*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_map_empty(p_new));
928*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_map_empty(p_old));
929*d6b92ffaSHans Petter Selasky
930*d6b92ffaSHans Petter Selasky itor1 = cl_map_head(p_map1);
931*d6b92ffaSHans Petter Selasky itor2 = cl_map_head(p_map2);
932*d6b92ffaSHans Petter Selasky
933*d6b92ffaSHans Petter Selasky /*
934*d6b92ffaSHans Petter Selasky * Note that the check is for the end, since duplicate items will remain
935*d6b92ffaSHans Petter Selasky * in their respective maps.
936*d6b92ffaSHans Petter Selasky */
937*d6b92ffaSHans Petter Selasky while (itor1 != cl_map_end(p_map1) && itor2 != cl_map_end(p_map2)) {
938*d6b92ffaSHans Petter Selasky key1 = cl_map_key(itor1);
939*d6b92ffaSHans Petter Selasky key2 = cl_map_key(itor2);
940*d6b92ffaSHans Petter Selasky if (key1 < key2) {
941*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_old, p_map1, &itor1);
942*d6b92ffaSHans Petter Selasky /* Check for failure. */
943*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) {
944*d6b92ffaSHans Petter Selasky /* Restore the initial state. */
945*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old);
946*d6b92ffaSHans Petter Selasky /* Return the failure status. */
947*d6b92ffaSHans Petter Selasky return (status);
948*d6b92ffaSHans Petter Selasky }
949*d6b92ffaSHans Petter Selasky } else if (key1 > key2) {
950*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_new, p_map2, &itor2);
951*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) {
952*d6b92ffaSHans Petter Selasky /* Restore the initial state. */
953*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old);
954*d6b92ffaSHans Petter Selasky /* Return the failure status. */
955*d6b92ffaSHans Petter Selasky return (status);
956*d6b92ffaSHans Petter Selasky }
957*d6b92ffaSHans Petter Selasky } else {
958*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */
959*d6b92ffaSHans Petter Selasky itor1 = cl_map_next(itor1);
960*d6b92ffaSHans Petter Selasky itor2 = cl_map_next(itor2);
961*d6b92ffaSHans Petter Selasky }
962*d6b92ffaSHans Petter Selasky }
963*d6b92ffaSHans Petter Selasky
964*d6b92ffaSHans Petter Selasky /* Process the remainder if either source map is empty. */
965*d6b92ffaSHans Petter Selasky while (itor2 != cl_map_end(p_map2)) {
966*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_new, p_map2, &itor2);
967*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) {
968*d6b92ffaSHans Petter Selasky /* Restore the initial state. */
969*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old);
970*d6b92ffaSHans Petter Selasky /* Return the failure status. */
971*d6b92ffaSHans Petter Selasky return (status);
972*d6b92ffaSHans Petter Selasky }
973*d6b92ffaSHans Petter Selasky }
974*d6b92ffaSHans Petter Selasky
975*d6b92ffaSHans Petter Selasky while (itor1 != cl_map_end(p_map1)) {
976*d6b92ffaSHans Petter Selasky status = __cl_map_delta_move(p_old, p_map1, &itor1);
977*d6b92ffaSHans Petter Selasky if (status != CL_SUCCESS) {
978*d6b92ffaSHans Petter Selasky /* Restore the initial state. */
979*d6b92ffaSHans Petter Selasky __cl_map_revert(p_map1, p_map2, p_new, p_old);
980*d6b92ffaSHans Petter Selasky /* Return the failure status. */
981*d6b92ffaSHans Petter Selasky return (status);
982*d6b92ffaSHans Petter Selasky }
983*d6b92ffaSHans Petter Selasky }
984*d6b92ffaSHans Petter Selasky
985*d6b92ffaSHans Petter Selasky return (CL_SUCCESS);
986*d6b92ffaSHans Petter Selasky }
987*d6b92ffaSHans Petter Selasky
988*d6b92ffaSHans Petter Selasky /******************************************************************************
989*d6b92ffaSHans Petter Selasky IMPLEMENTATION OF FLEXI MAP
990*d6b92ffaSHans Petter Selasky ******************************************************************************/
991*d6b92ffaSHans Petter Selasky
992*d6b92ffaSHans Petter Selasky /*
993*d6b92ffaSHans Petter Selasky * Get the root.
994*d6b92ffaSHans Petter Selasky */
__cl_fmap_root(IN const cl_fmap_t * const p_map)995*d6b92ffaSHans Petter Selasky static inline cl_fmap_item_t *__cl_fmap_root(IN const cl_fmap_t * const p_map)
996*d6b92ffaSHans Petter Selasky {
997*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
998*d6b92ffaSHans Petter Selasky return (p_map->root.p_left);
999*d6b92ffaSHans Petter Selasky }
1000*d6b92ffaSHans Petter Selasky
1001*d6b92ffaSHans Petter Selasky /*
1002*d6b92ffaSHans Petter Selasky * Returns whether a given item is on the left of its parent.
1003*d6b92ffaSHans Petter Selasky */
__cl_fmap_is_left_child(IN const cl_fmap_item_t * const p_item)1004*d6b92ffaSHans Petter Selasky static boolean_t __cl_fmap_is_left_child(IN const cl_fmap_item_t * const p_item)
1005*d6b92ffaSHans Petter Selasky {
1006*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1007*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up);
1008*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item);
1009*d6b92ffaSHans Petter Selasky
1010*d6b92ffaSHans Petter Selasky return (p_item->p_up->p_left == p_item);
1011*d6b92ffaSHans Petter Selasky }
1012*d6b92ffaSHans Petter Selasky
1013*d6b92ffaSHans Petter Selasky /*
1014*d6b92ffaSHans Petter Selasky * Retrieve the pointer to the parent's pointer to an item.
1015*d6b92ffaSHans Petter Selasky */
__cl_fmap_get_parent_ptr_to_item(IN cl_fmap_item_t * const p_item)1016*d6b92ffaSHans Petter Selasky static cl_fmap_item_t **__cl_fmap_get_parent_ptr_to_item(IN cl_fmap_item_t *
1017*d6b92ffaSHans Petter Selasky const p_item)
1018*d6b92ffaSHans Petter Selasky {
1019*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1020*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up);
1021*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up != p_item);
1022*d6b92ffaSHans Petter Selasky
1023*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item))
1024*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_left);
1025*d6b92ffaSHans Petter Selasky
1026*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_up->p_right == p_item);
1027*d6b92ffaSHans Petter Selasky return (&p_item->p_up->p_right);
1028*d6b92ffaSHans Petter Selasky }
1029*d6b92ffaSHans Petter Selasky
1030*d6b92ffaSHans Petter Selasky /*
1031*d6b92ffaSHans Petter Selasky * Rotate a node to the left. This rotation affects the least number of links
1032*d6b92ffaSHans Petter Selasky * between nodes and brings the level of C up by one while increasing the depth
1033*d6b92ffaSHans Petter Selasky * of A one. Note that the links to/from W, X, Y, and Z are not affected.
1034*d6b92ffaSHans Petter Selasky *
1035*d6b92ffaSHans Petter Selasky * R R
1036*d6b92ffaSHans Petter Selasky * | |
1037*d6b92ffaSHans Petter Selasky * A C
1038*d6b92ffaSHans Petter Selasky * / \ / \
1039*d6b92ffaSHans Petter Selasky * W C A Z
1040*d6b92ffaSHans Petter Selasky * / \ / \
1041*d6b92ffaSHans Petter Selasky * B Z W B
1042*d6b92ffaSHans Petter Selasky * / \ / \
1043*d6b92ffaSHans Petter Selasky * X Y X Y
1044*d6b92ffaSHans Petter Selasky */
__cl_fmap_rot_left(IN cl_fmap_t * const p_map,IN cl_fmap_item_t * const p_item)1045*d6b92ffaSHans Petter Selasky static void __cl_fmap_rot_left(IN cl_fmap_t * const p_map,
1046*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item)
1047*d6b92ffaSHans Petter Selasky {
1048*d6b92ffaSHans Petter Selasky cl_fmap_item_t **pp_root;
1049*d6b92ffaSHans Petter Selasky
1050*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1051*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1052*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_right != &p_map->nil);
1053*d6b92ffaSHans Petter Selasky
1054*d6b92ffaSHans Petter Selasky pp_root = __cl_fmap_get_parent_ptr_to_item(p_item);
1055*d6b92ffaSHans Petter Selasky
1056*d6b92ffaSHans Petter Selasky /* Point R to C instead of A. */
1057*d6b92ffaSHans Petter Selasky *pp_root = p_item->p_right;
1058*d6b92ffaSHans Petter Selasky /* Set C's parent to R. */
1059*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up;
1060*d6b92ffaSHans Petter Selasky
1061*d6b92ffaSHans Petter Selasky /* Set A's right to B */
1062*d6b92ffaSHans Petter Selasky p_item->p_right = (*pp_root)->p_left;
1063*d6b92ffaSHans Petter Selasky /*
1064*d6b92ffaSHans Petter Selasky * Set B's parent to A. We trap for B being NIL since the
1065*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing.
1066*d6b92ffaSHans Petter Selasky */
1067*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_left != &p_map->nil)
1068*d6b92ffaSHans Petter Selasky (*pp_root)->p_left->p_up = p_item;
1069*d6b92ffaSHans Petter Selasky
1070*d6b92ffaSHans Petter Selasky /* Set C's left to A. */
1071*d6b92ffaSHans Petter Selasky (*pp_root)->p_left = p_item;
1072*d6b92ffaSHans Petter Selasky /* Set A's parent to C. */
1073*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root;
1074*d6b92ffaSHans Petter Selasky }
1075*d6b92ffaSHans Petter Selasky
1076*d6b92ffaSHans Petter Selasky /*
1077*d6b92ffaSHans Petter Selasky * Rotate a node to the right. This rotation affects the least number of links
1078*d6b92ffaSHans Petter Selasky * between nodes and brings the level of A up by one while increasing the depth
1079*d6b92ffaSHans Petter Selasky * of C one. Note that the links to/from W, X, Y, and Z are not affected.
1080*d6b92ffaSHans Petter Selasky *
1081*d6b92ffaSHans Petter Selasky * R R
1082*d6b92ffaSHans Petter Selasky * | |
1083*d6b92ffaSHans Petter Selasky * C A
1084*d6b92ffaSHans Petter Selasky * / \ / \
1085*d6b92ffaSHans Petter Selasky * A Z W C
1086*d6b92ffaSHans Petter Selasky * / \ / \
1087*d6b92ffaSHans Petter Selasky * W B B Z
1088*d6b92ffaSHans Petter Selasky * / \ / \
1089*d6b92ffaSHans Petter Selasky * X Y X Y
1090*d6b92ffaSHans Petter Selasky */
__cl_fmap_rot_right(IN cl_fmap_t * const p_map,IN cl_fmap_item_t * const p_item)1091*d6b92ffaSHans Petter Selasky static void __cl_fmap_rot_right(IN cl_fmap_t * const p_map,
1092*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item)
1093*d6b92ffaSHans Petter Selasky {
1094*d6b92ffaSHans Petter Selasky cl_fmap_item_t **pp_root;
1095*d6b92ffaSHans Petter Selasky
1096*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1097*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1098*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_left != &p_map->nil);
1099*d6b92ffaSHans Petter Selasky
1100*d6b92ffaSHans Petter Selasky /* Point R to A instead of C. */
1101*d6b92ffaSHans Petter Selasky pp_root = __cl_fmap_get_parent_ptr_to_item(p_item);
1102*d6b92ffaSHans Petter Selasky (*pp_root) = p_item->p_left;
1103*d6b92ffaSHans Petter Selasky /* Set A's parent to R. */
1104*d6b92ffaSHans Petter Selasky (*pp_root)->p_up = p_item->p_up;
1105*d6b92ffaSHans Petter Selasky
1106*d6b92ffaSHans Petter Selasky /* Set C's left to B */
1107*d6b92ffaSHans Petter Selasky p_item->p_left = (*pp_root)->p_right;
1108*d6b92ffaSHans Petter Selasky /*
1109*d6b92ffaSHans Petter Selasky * Set B's parent to C. We trap for B being NIL since the
1110*d6b92ffaSHans Petter Selasky * caller may depend on NIL not changing.
1111*d6b92ffaSHans Petter Selasky */
1112*d6b92ffaSHans Petter Selasky if ((*pp_root)->p_right != &p_map->nil)
1113*d6b92ffaSHans Petter Selasky (*pp_root)->p_right->p_up = p_item;
1114*d6b92ffaSHans Petter Selasky
1115*d6b92ffaSHans Petter Selasky /* Set A's right to C. */
1116*d6b92ffaSHans Petter Selasky (*pp_root)->p_right = p_item;
1117*d6b92ffaSHans Petter Selasky /* Set C's parent to A. */
1118*d6b92ffaSHans Petter Selasky p_item->p_up = *pp_root;
1119*d6b92ffaSHans Petter Selasky }
1120*d6b92ffaSHans Petter Selasky
cl_fmap_init(IN cl_fmap_t * const p_map,IN cl_pfn_fmap_cmp_t pfn_compare)1121*d6b92ffaSHans Petter Selasky void cl_fmap_init(IN cl_fmap_t * const p_map, IN cl_pfn_fmap_cmp_t pfn_compare)
1122*d6b92ffaSHans Petter Selasky {
1123*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1124*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_compare);
1125*d6b92ffaSHans Petter Selasky
1126*d6b92ffaSHans Petter Selasky memset(p_map, 0, sizeof(cl_fmap_t));
1127*d6b92ffaSHans Petter Selasky
1128*d6b92ffaSHans Petter Selasky /* special setup for the root node */
1129*d6b92ffaSHans Petter Selasky p_map->root.p_up = &p_map->root;
1130*d6b92ffaSHans Petter Selasky p_map->root.p_left = &p_map->nil;
1131*d6b92ffaSHans Petter Selasky p_map->root.p_right = &p_map->nil;
1132*d6b92ffaSHans Petter Selasky p_map->root.color = CL_MAP_BLACK;
1133*d6b92ffaSHans Petter Selasky
1134*d6b92ffaSHans Petter Selasky /* Setup the node used as terminator for all leaves. */
1135*d6b92ffaSHans Petter Selasky p_map->nil.p_up = &p_map->nil;
1136*d6b92ffaSHans Petter Selasky p_map->nil.p_left = &p_map->nil;
1137*d6b92ffaSHans Petter Selasky p_map->nil.p_right = &p_map->nil;
1138*d6b92ffaSHans Petter Selasky p_map->nil.color = CL_MAP_BLACK;
1139*d6b92ffaSHans Petter Selasky
1140*d6b92ffaSHans Petter Selasky /* Store the compare function pointer. */
1141*d6b92ffaSHans Petter Selasky p_map->pfn_compare = pfn_compare;
1142*d6b92ffaSHans Petter Selasky
1143*d6b92ffaSHans Petter Selasky p_map->state = CL_INITIALIZED;
1144*d6b92ffaSHans Petter Selasky
1145*d6b92ffaSHans Petter Selasky cl_fmap_remove_all(p_map);
1146*d6b92ffaSHans Petter Selasky }
1147*d6b92ffaSHans Petter Selasky
cl_fmap_match(IN const cl_fmap_t * const p_map,IN const void * const p_key,IN cl_pfn_fmap_cmp_t pfn_compare)1148*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_match(IN const cl_fmap_t * const p_map,
1149*d6b92ffaSHans Petter Selasky IN const void *const p_key,
1150*d6b92ffaSHans Petter Selasky IN cl_pfn_fmap_cmp_t pfn_compare)
1151*d6b92ffaSHans Petter Selasky {
1152*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item;
1153*d6b92ffaSHans Petter Selasky int cmp;
1154*d6b92ffaSHans Petter Selasky
1155*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1156*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1157*d6b92ffaSHans Petter Selasky
1158*d6b92ffaSHans Petter Selasky p_item = __cl_fmap_root(p_map);
1159*d6b92ffaSHans Petter Selasky
1160*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) {
1161*d6b92ffaSHans Petter Selasky cmp = pfn_compare ? pfn_compare(p_key, p_item->p_key) :
1162*d6b92ffaSHans Petter Selasky p_map->pfn_compare(p_key, p_item->p_key);
1163*d6b92ffaSHans Petter Selasky
1164*d6b92ffaSHans Petter Selasky if (!cmp)
1165*d6b92ffaSHans Petter Selasky break; /* just right */
1166*d6b92ffaSHans Petter Selasky
1167*d6b92ffaSHans Petter Selasky if (cmp < 0)
1168*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */
1169*d6b92ffaSHans Petter Selasky else
1170*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big */
1171*d6b92ffaSHans Petter Selasky }
1172*d6b92ffaSHans Petter Selasky
1173*d6b92ffaSHans Petter Selasky return (p_item);
1174*d6b92ffaSHans Petter Selasky }
1175*d6b92ffaSHans Petter Selasky
cl_fmap_get(IN const cl_fmap_t * const p_map,IN const void * const p_key)1176*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map,
1177*d6b92ffaSHans Petter Selasky IN const void *const p_key)
1178*d6b92ffaSHans Petter Selasky {
1179*d6b92ffaSHans Petter Selasky return cl_fmap_match(p_map, p_key, p_map->pfn_compare);
1180*d6b92ffaSHans Petter Selasky }
1181*d6b92ffaSHans Petter Selasky
cl_fmap_get_next(IN const cl_fmap_t * const p_map,IN const void * const p_key)1182*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map,
1183*d6b92ffaSHans Petter Selasky IN const void *const p_key)
1184*d6b92ffaSHans Petter Selasky {
1185*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item;
1186*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item_found;
1187*d6b92ffaSHans Petter Selasky int cmp;
1188*d6b92ffaSHans Petter Selasky
1189*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1190*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1191*d6b92ffaSHans Petter Selasky
1192*d6b92ffaSHans Petter Selasky p_item = __cl_fmap_root(p_map);
1193*d6b92ffaSHans Petter Selasky p_item_found = (cl_fmap_item_t *) & p_map->nil;
1194*d6b92ffaSHans Petter Selasky
1195*d6b92ffaSHans Petter Selasky while (p_item != &p_map->nil) {
1196*d6b92ffaSHans Petter Selasky cmp = p_map->pfn_compare(p_key, p_item->p_key);
1197*d6b92ffaSHans Petter Selasky
1198*d6b92ffaSHans Petter Selasky if (cmp < 0) {
1199*d6b92ffaSHans Petter Selasky p_item_found = p_item;
1200*d6b92ffaSHans Petter Selasky p_item = p_item->p_left; /* too small */
1201*d6b92ffaSHans Petter Selasky } else {
1202*d6b92ffaSHans Petter Selasky p_item = p_item->p_right; /* too big or match */
1203*d6b92ffaSHans Petter Selasky }
1204*d6b92ffaSHans Petter Selasky }
1205*d6b92ffaSHans Petter Selasky
1206*d6b92ffaSHans Petter Selasky return (p_item_found);
1207*d6b92ffaSHans Petter Selasky }
1208*d6b92ffaSHans Petter Selasky
cl_fmap_apply_func(IN const cl_fmap_t * const p_map,IN cl_pfn_fmap_apply_t pfn_func,IN const void * const context)1209*d6b92ffaSHans Petter Selasky void cl_fmap_apply_func(IN const cl_fmap_t * const p_map,
1210*d6b92ffaSHans Petter Selasky IN cl_pfn_fmap_apply_t pfn_func,
1211*d6b92ffaSHans Petter Selasky IN const void *const context)
1212*d6b92ffaSHans Petter Selasky {
1213*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_fmap_item;
1214*d6b92ffaSHans Petter Selasky
1215*d6b92ffaSHans Petter Selasky /* Note that context can have any arbitrary value. */
1216*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1217*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1218*d6b92ffaSHans Petter Selasky CL_ASSERT(pfn_func);
1219*d6b92ffaSHans Petter Selasky
1220*d6b92ffaSHans Petter Selasky p_fmap_item = cl_fmap_head(p_map);
1221*d6b92ffaSHans Petter Selasky while (p_fmap_item != cl_fmap_end(p_map)) {
1222*d6b92ffaSHans Petter Selasky pfn_func(p_fmap_item, (void *)context);
1223*d6b92ffaSHans Petter Selasky p_fmap_item = cl_fmap_next(p_fmap_item);
1224*d6b92ffaSHans Petter Selasky }
1225*d6b92ffaSHans Petter Selasky }
1226*d6b92ffaSHans Petter Selasky
1227*d6b92ffaSHans Petter Selasky /*
1228*d6b92ffaSHans Petter Selasky * Balance a tree starting at a given item back to the root.
1229*d6b92ffaSHans Petter Selasky */
__cl_fmap_ins_bal(IN cl_fmap_t * const p_map,IN cl_fmap_item_t * p_item)1230*d6b92ffaSHans Petter Selasky static void __cl_fmap_ins_bal(IN cl_fmap_t * const p_map,
1231*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * p_item)
1232*d6b92ffaSHans Petter Selasky {
1233*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_grand_uncle;
1234*d6b92ffaSHans Petter Selasky
1235*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1236*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1237*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item != &p_map->root);
1238*d6b92ffaSHans Petter Selasky
1239*d6b92ffaSHans Petter Selasky while (p_item->p_up->color == CL_MAP_RED) {
1240*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item->p_up)) {
1241*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_right;
1242*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle);
1243*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) {
1244*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK;
1245*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1246*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
1247*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up;
1248*d6b92ffaSHans Petter Selasky continue;
1249*d6b92ffaSHans Petter Selasky }
1250*d6b92ffaSHans Petter Selasky
1251*d6b92ffaSHans Petter Selasky if (!__cl_fmap_is_left_child(p_item)) {
1252*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
1253*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item);
1254*d6b92ffaSHans Petter Selasky }
1255*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1256*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
1257*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up->p_up);
1258*d6b92ffaSHans Petter Selasky } else {
1259*d6b92ffaSHans Petter Selasky p_grand_uncle = p_item->p_up->p_up->p_left;
1260*d6b92ffaSHans Petter Selasky CL_ASSERT(p_grand_uncle);
1261*d6b92ffaSHans Petter Selasky if (p_grand_uncle->color == CL_MAP_RED) {
1262*d6b92ffaSHans Petter Selasky p_grand_uncle->color = CL_MAP_BLACK;
1263*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1264*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
1265*d6b92ffaSHans Petter Selasky p_item = p_item->p_up->p_up;
1266*d6b92ffaSHans Petter Selasky continue;
1267*d6b92ffaSHans Petter Selasky }
1268*d6b92ffaSHans Petter Selasky
1269*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item)) {
1270*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
1271*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item);
1272*d6b92ffaSHans Petter Selasky }
1273*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1274*d6b92ffaSHans Petter Selasky p_item->p_up->p_up->color = CL_MAP_RED;
1275*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up->p_up);
1276*d6b92ffaSHans Petter Selasky }
1277*d6b92ffaSHans Petter Selasky }
1278*d6b92ffaSHans Petter Selasky }
1279*d6b92ffaSHans Petter Selasky
cl_fmap_insert(IN cl_fmap_t * const p_map,IN const void * const p_key,IN cl_fmap_item_t * const p_item)1280*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_insert(IN cl_fmap_t * const p_map,
1281*d6b92ffaSHans Petter Selasky IN const void *const p_key,
1282*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item)
1283*d6b92ffaSHans Petter Selasky {
1284*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_insert_at, *p_comp_item;
1285*d6b92ffaSHans Petter Selasky int cmp = 0;
1286*d6b92ffaSHans Petter Selasky
1287*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1288*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1289*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1290*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.p_up == &p_map->root);
1291*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->root.color != CL_MAP_RED);
1292*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED);
1293*d6b92ffaSHans Petter Selasky
1294*d6b92ffaSHans Petter Selasky p_item->p_left = &p_map->nil;
1295*d6b92ffaSHans Petter Selasky p_item->p_right = &p_map->nil;
1296*d6b92ffaSHans Petter Selasky p_item->p_key = p_key;
1297*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_RED;
1298*d6b92ffaSHans Petter Selasky
1299*d6b92ffaSHans Petter Selasky /* Find the insertion location. */
1300*d6b92ffaSHans Petter Selasky p_insert_at = &p_map->root;
1301*d6b92ffaSHans Petter Selasky p_comp_item = __cl_fmap_root(p_map);
1302*d6b92ffaSHans Petter Selasky
1303*d6b92ffaSHans Petter Selasky while (p_comp_item != &p_map->nil) {
1304*d6b92ffaSHans Petter Selasky p_insert_at = p_comp_item;
1305*d6b92ffaSHans Petter Selasky
1306*d6b92ffaSHans Petter Selasky cmp = p_map->pfn_compare(p_key, p_insert_at->p_key);
1307*d6b92ffaSHans Petter Selasky
1308*d6b92ffaSHans Petter Selasky if (!cmp)
1309*d6b92ffaSHans Petter Selasky return (p_insert_at);
1310*d6b92ffaSHans Petter Selasky
1311*d6b92ffaSHans Petter Selasky /* Traverse the tree until the correct insertion point is found. */
1312*d6b92ffaSHans Petter Selasky if (cmp < 0)
1313*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_left;
1314*d6b92ffaSHans Petter Selasky else
1315*d6b92ffaSHans Petter Selasky p_comp_item = p_insert_at->p_right;
1316*d6b92ffaSHans Petter Selasky }
1317*d6b92ffaSHans Petter Selasky
1318*d6b92ffaSHans Petter Selasky CL_ASSERT(p_insert_at != &p_map->nil);
1319*d6b92ffaSHans Petter Selasky CL_ASSERT(p_comp_item == &p_map->nil);
1320*d6b92ffaSHans Petter Selasky /* Insert the item. */
1321*d6b92ffaSHans Petter Selasky if (p_insert_at == &p_map->root) {
1322*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item;
1323*d6b92ffaSHans Petter Selasky /*
1324*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
1325*d6b92ffaSHans Petter Selasky * the existing item.
1326*d6b92ffaSHans Petter Selasky */
1327*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_map->nil.pool_item.list_item,
1328*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
1329*d6b92ffaSHans Petter Selasky } else if (cmp < 0) {
1330*d6b92ffaSHans Petter Selasky p_insert_at->p_left = p_item;
1331*d6b92ffaSHans Petter Selasky /*
1332*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
1333*d6b92ffaSHans Petter Selasky * the existing item.
1334*d6b92ffaSHans Petter Selasky */
1335*d6b92ffaSHans Petter Selasky __cl_primitive_insert(&p_insert_at->pool_item.list_item,
1336*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
1337*d6b92ffaSHans Petter Selasky } else {
1338*d6b92ffaSHans Petter Selasky p_insert_at->p_right = p_item;
1339*d6b92ffaSHans Petter Selasky /*
1340*d6b92ffaSHans Petter Selasky * Primitive insert places the new item in front of
1341*d6b92ffaSHans Petter Selasky * the existing item.
1342*d6b92ffaSHans Petter Selasky */
1343*d6b92ffaSHans Petter Selasky __cl_primitive_insert(p_insert_at->pool_item.list_item.p_next,
1344*d6b92ffaSHans Petter Selasky &p_item->pool_item.list_item);
1345*d6b92ffaSHans Petter Selasky }
1346*d6b92ffaSHans Petter Selasky /* Increase the count. */
1347*d6b92ffaSHans Petter Selasky p_map->count++;
1348*d6b92ffaSHans Petter Selasky
1349*d6b92ffaSHans Petter Selasky p_item->p_up = p_insert_at;
1350*d6b92ffaSHans Petter Selasky
1351*d6b92ffaSHans Petter Selasky /*
1352*d6b92ffaSHans Petter Selasky * We have added depth to this section of the tree.
1353*d6b92ffaSHans Petter Selasky * Rebalance as necessary as we retrace our path through the tree
1354*d6b92ffaSHans Petter Selasky * and update colors.
1355*d6b92ffaSHans Petter Selasky */
1356*d6b92ffaSHans Petter Selasky __cl_fmap_ins_bal(p_map, p_item);
1357*d6b92ffaSHans Petter Selasky
1358*d6b92ffaSHans Petter Selasky __cl_fmap_root(p_map)->color = CL_MAP_BLACK;
1359*d6b92ffaSHans Petter Selasky
1360*d6b92ffaSHans Petter Selasky /*
1361*d6b92ffaSHans Petter Selasky * Note that it is not necessary to re-color the nil node black because all
1362*d6b92ffaSHans Petter Selasky * red color assignments are made via the p_up pointer, and nil is never
1363*d6b92ffaSHans Petter Selasky * set as the value of a p_up pointer.
1364*d6b92ffaSHans Petter Selasky */
1365*d6b92ffaSHans Petter Selasky
1366*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
1367*d6b92ffaSHans Petter Selasky /* Set the pointer to the map in the map item for consistency checking. */
1368*d6b92ffaSHans Petter Selasky p_item->p_map = p_map;
1369*d6b92ffaSHans Petter Selasky #endif
1370*d6b92ffaSHans Petter Selasky
1371*d6b92ffaSHans Petter Selasky return (p_item);
1372*d6b92ffaSHans Petter Selasky }
1373*d6b92ffaSHans Petter Selasky
__cl_fmap_del_bal(IN cl_fmap_t * const p_map,IN cl_fmap_item_t * p_item)1374*d6b92ffaSHans Petter Selasky static void __cl_fmap_del_bal(IN cl_fmap_t * const p_map,
1375*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * p_item)
1376*d6b92ffaSHans Petter Selasky {
1377*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_uncle;
1378*d6b92ffaSHans Petter Selasky
1379*d6b92ffaSHans Petter Selasky while ((p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root)) {
1380*d6b92ffaSHans Petter Selasky if (__cl_fmap_is_left_child(p_item)) {
1381*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
1382*d6b92ffaSHans Petter Selasky
1383*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) {
1384*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK;
1385*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED;
1386*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up);
1387*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
1388*d6b92ffaSHans Petter Selasky }
1389*d6b92ffaSHans Petter Selasky
1390*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) {
1391*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) {
1392*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
1393*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
1394*d6b92ffaSHans Petter Selasky continue;
1395*d6b92ffaSHans Petter Selasky }
1396*d6b92ffaSHans Petter Selasky
1397*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK;
1398*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
1399*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_uncle);
1400*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_right;
1401*d6b92ffaSHans Petter Selasky }
1402*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color;
1403*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1404*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK;
1405*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_item->p_up);
1406*d6b92ffaSHans Petter Selasky break;
1407*d6b92ffaSHans Petter Selasky } else {
1408*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
1409*d6b92ffaSHans Petter Selasky
1410*d6b92ffaSHans Petter Selasky if (p_uncle->color == CL_MAP_RED) {
1411*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_BLACK;
1412*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_RED;
1413*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up);
1414*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
1415*d6b92ffaSHans Petter Selasky }
1416*d6b92ffaSHans Petter Selasky
1417*d6b92ffaSHans Petter Selasky if (p_uncle->p_left->color != CL_MAP_RED) {
1418*d6b92ffaSHans Petter Selasky if (p_uncle->p_right->color != CL_MAP_RED) {
1419*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
1420*d6b92ffaSHans Petter Selasky p_item = p_item->p_up;
1421*d6b92ffaSHans Petter Selasky continue;
1422*d6b92ffaSHans Petter Selasky }
1423*d6b92ffaSHans Petter Selasky
1424*d6b92ffaSHans Petter Selasky p_uncle->p_right->color = CL_MAP_BLACK;
1425*d6b92ffaSHans Petter Selasky p_uncle->color = CL_MAP_RED;
1426*d6b92ffaSHans Petter Selasky __cl_fmap_rot_left(p_map, p_uncle);
1427*d6b92ffaSHans Petter Selasky p_uncle = p_item->p_up->p_left;
1428*d6b92ffaSHans Petter Selasky }
1429*d6b92ffaSHans Petter Selasky p_uncle->color = p_item->p_up->color;
1430*d6b92ffaSHans Petter Selasky p_item->p_up->color = CL_MAP_BLACK;
1431*d6b92ffaSHans Petter Selasky p_uncle->p_left->color = CL_MAP_BLACK;
1432*d6b92ffaSHans Petter Selasky __cl_fmap_rot_right(p_map, p_item->p_up);
1433*d6b92ffaSHans Petter Selasky break;
1434*d6b92ffaSHans Petter Selasky }
1435*d6b92ffaSHans Petter Selasky }
1436*d6b92ffaSHans Petter Selasky p_item->color = CL_MAP_BLACK;
1437*d6b92ffaSHans Petter Selasky }
1438*d6b92ffaSHans Petter Selasky
cl_fmap_remove_item(IN cl_fmap_t * const p_map,IN cl_fmap_item_t * const p_item)1439*d6b92ffaSHans Petter Selasky void cl_fmap_remove_item(IN cl_fmap_t * const p_map,
1440*d6b92ffaSHans Petter Selasky IN cl_fmap_item_t * const p_item)
1441*d6b92ffaSHans Petter Selasky {
1442*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_child, *p_del_item;
1443*d6b92ffaSHans Petter Selasky
1444*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1445*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1446*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item);
1447*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item->p_map == p_map);
1448*d6b92ffaSHans Petter Selasky
1449*d6b92ffaSHans Petter Selasky if (p_item == cl_fmap_end(p_map))
1450*d6b92ffaSHans Petter Selasky return;
1451*d6b92ffaSHans Petter Selasky
1452*d6b92ffaSHans Petter Selasky if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) {
1453*d6b92ffaSHans Petter Selasky /* The item being removed has children on at most on side. */
1454*d6b92ffaSHans Petter Selasky p_del_item = p_item;
1455*d6b92ffaSHans Petter Selasky } else {
1456*d6b92ffaSHans Petter Selasky /*
1457*d6b92ffaSHans Petter Selasky * The item being removed has children on both side.
1458*d6b92ffaSHans Petter Selasky * We select the item that will replace it. After removing
1459*d6b92ffaSHans Petter Selasky * the substitute item and rebalancing, the tree will have the
1460*d6b92ffaSHans Petter Selasky * correct topology. Exchanging the substitute for the item
1461*d6b92ffaSHans Petter Selasky * will finalize the removal.
1462*d6b92ffaSHans Petter Selasky */
1463*d6b92ffaSHans Petter Selasky p_del_item = cl_fmap_next(p_item);
1464*d6b92ffaSHans Petter Selasky CL_ASSERT(p_del_item != &p_map->nil);
1465*d6b92ffaSHans Petter Selasky }
1466*d6b92ffaSHans Petter Selasky
1467*d6b92ffaSHans Petter Selasky /* Remove the item from the list. */
1468*d6b92ffaSHans Petter Selasky __cl_primitive_remove(&p_item->pool_item.list_item);
1469*d6b92ffaSHans Petter Selasky /* Decrement the item count. */
1470*d6b92ffaSHans Petter Selasky p_map->count--;
1471*d6b92ffaSHans Petter Selasky
1472*d6b92ffaSHans Petter Selasky /* Get the pointer to the new root's child, if any. */
1473*d6b92ffaSHans Petter Selasky if (p_del_item->p_left != &p_map->nil)
1474*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_left;
1475*d6b92ffaSHans Petter Selasky else
1476*d6b92ffaSHans Petter Selasky p_child = p_del_item->p_right;
1477*d6b92ffaSHans Petter Selasky
1478*d6b92ffaSHans Petter Selasky /*
1479*d6b92ffaSHans Petter Selasky * This assignment may modify the parent pointer of the nil node.
1480*d6b92ffaSHans Petter Selasky * This is inconsequential.
1481*d6b92ffaSHans Petter Selasky */
1482*d6b92ffaSHans Petter Selasky p_child->p_up = p_del_item->p_up;
1483*d6b92ffaSHans Petter Selasky (*__cl_fmap_get_parent_ptr_to_item(p_del_item)) = p_child;
1484*d6b92ffaSHans Petter Selasky
1485*d6b92ffaSHans Petter Selasky if (p_del_item->color != CL_MAP_RED)
1486*d6b92ffaSHans Petter Selasky __cl_fmap_del_bal(p_map, p_child);
1487*d6b92ffaSHans Petter Selasky
1488*d6b92ffaSHans Petter Selasky /*
1489*d6b92ffaSHans Petter Selasky * Note that the splicing done below does not need to occur before
1490*d6b92ffaSHans Petter Selasky * the tree is balanced, since the actual topology changes are made by the
1491*d6b92ffaSHans Petter Selasky * preceding code. The topology is preserved by the color assignment made
1492*d6b92ffaSHans Petter Selasky * below (reader should be reminded that p_del_item == p_item in some cases).
1493*d6b92ffaSHans Petter Selasky */
1494*d6b92ffaSHans Petter Selasky if (p_del_item != p_item) {
1495*d6b92ffaSHans Petter Selasky /*
1496*d6b92ffaSHans Petter Selasky * Finalize the removal of the specified item by exchanging it with
1497*d6b92ffaSHans Petter Selasky * the substitute which we removed above.
1498*d6b92ffaSHans Petter Selasky */
1499*d6b92ffaSHans Petter Selasky p_del_item->p_up = p_item->p_up;
1500*d6b92ffaSHans Petter Selasky p_del_item->p_left = p_item->p_left;
1501*d6b92ffaSHans Petter Selasky p_del_item->p_right = p_item->p_right;
1502*d6b92ffaSHans Petter Selasky (*__cl_fmap_get_parent_ptr_to_item(p_item)) = p_del_item;
1503*d6b92ffaSHans Petter Selasky p_item->p_right->p_up = p_del_item;
1504*d6b92ffaSHans Petter Selasky p_item->p_left->p_up = p_del_item;
1505*d6b92ffaSHans Petter Selasky p_del_item->color = p_item->color;
1506*d6b92ffaSHans Petter Selasky }
1507*d6b92ffaSHans Petter Selasky
1508*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->nil.color != CL_MAP_RED);
1509*d6b92ffaSHans Petter Selasky
1510*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
1511*d6b92ffaSHans Petter Selasky /* Clear the pointer to the map since the item has been removed. */
1512*d6b92ffaSHans Petter Selasky p_item->p_map = NULL;
1513*d6b92ffaSHans Petter Selasky #endif
1514*d6b92ffaSHans Petter Selasky }
1515*d6b92ffaSHans Petter Selasky
cl_fmap_remove(IN cl_fmap_t * const p_map,IN const void * const p_key)1516*d6b92ffaSHans Petter Selasky cl_fmap_item_t *cl_fmap_remove(IN cl_fmap_t * const p_map,
1517*d6b92ffaSHans Petter Selasky IN const void *const p_key)
1518*d6b92ffaSHans Petter Selasky {
1519*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item;
1520*d6b92ffaSHans Petter Selasky
1521*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map);
1522*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map->state == CL_INITIALIZED);
1523*d6b92ffaSHans Petter Selasky
1524*d6b92ffaSHans Petter Selasky /* Seek the node with the specified key */
1525*d6b92ffaSHans Petter Selasky p_item = cl_fmap_get(p_map, p_key);
1526*d6b92ffaSHans Petter Selasky
1527*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_map, p_item);
1528*d6b92ffaSHans Petter Selasky
1529*d6b92ffaSHans Petter Selasky return (p_item);
1530*d6b92ffaSHans Petter Selasky }
1531*d6b92ffaSHans Petter Selasky
cl_fmap_merge(OUT cl_fmap_t * const p_dest_map,IN OUT cl_fmap_t * const p_src_map)1532*d6b92ffaSHans Petter Selasky void cl_fmap_merge(OUT cl_fmap_t * const p_dest_map,
1533*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_src_map)
1534*d6b92ffaSHans Petter Selasky {
1535*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item, *p_item2, *p_next;
1536*d6b92ffaSHans Petter Selasky
1537*d6b92ffaSHans Petter Selasky CL_ASSERT(p_dest_map);
1538*d6b92ffaSHans Petter Selasky CL_ASSERT(p_src_map);
1539*d6b92ffaSHans Petter Selasky
1540*d6b92ffaSHans Petter Selasky p_item = cl_fmap_head(p_src_map);
1541*d6b92ffaSHans Petter Selasky
1542*d6b92ffaSHans Petter Selasky while (p_item != cl_fmap_end(p_src_map)) {
1543*d6b92ffaSHans Petter Selasky p_next = cl_fmap_next(p_item);
1544*d6b92ffaSHans Petter Selasky
1545*d6b92ffaSHans Petter Selasky /* Remove the item from its current map. */
1546*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_src_map, p_item);
1547*d6b92ffaSHans Petter Selasky /* Insert the item into the destination map. */
1548*d6b92ffaSHans Petter Selasky p_item2 =
1549*d6b92ffaSHans Petter Selasky cl_fmap_insert(p_dest_map, cl_fmap_key(p_item), p_item);
1550*d6b92ffaSHans Petter Selasky /* Check that the item was successfully inserted. */
1551*d6b92ffaSHans Petter Selasky if (p_item2 != p_item) {
1552*d6b92ffaSHans Petter Selasky /* Put the item in back in the source map. */
1553*d6b92ffaSHans Petter Selasky p_item2 =
1554*d6b92ffaSHans Petter Selasky cl_fmap_insert(p_src_map, cl_fmap_key(p_item),
1555*d6b92ffaSHans Petter Selasky p_item);
1556*d6b92ffaSHans Petter Selasky CL_ASSERT(p_item2 == p_item);
1557*d6b92ffaSHans Petter Selasky }
1558*d6b92ffaSHans Petter Selasky p_item = p_next;
1559*d6b92ffaSHans Petter Selasky }
1560*d6b92ffaSHans Petter Selasky }
1561*d6b92ffaSHans Petter Selasky
__cl_fmap_delta_move(IN OUT cl_fmap_t * const p_dest,IN OUT cl_fmap_t * const p_src,IN OUT cl_fmap_item_t ** const pp_item)1562*d6b92ffaSHans Petter Selasky static void __cl_fmap_delta_move(IN OUT cl_fmap_t * const p_dest,
1563*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_src,
1564*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_item_t ** const pp_item)
1565*d6b92ffaSHans Petter Selasky {
1566*d6b92ffaSHans Petter Selasky cl_fmap_item_t __attribute__((__unused__)) *p_temp;
1567*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_next;
1568*d6b92ffaSHans Petter Selasky
1569*d6b92ffaSHans Petter Selasky /*
1570*d6b92ffaSHans Petter Selasky * Get the next item so that we can ensure that pp_item points to
1571*d6b92ffaSHans Petter Selasky * a valid item upon return from the function.
1572*d6b92ffaSHans Petter Selasky */
1573*d6b92ffaSHans Petter Selasky p_next = cl_fmap_next(*pp_item);
1574*d6b92ffaSHans Petter Selasky /* Move the old item from its current map the the old map. */
1575*d6b92ffaSHans Petter Selasky cl_fmap_remove_item(p_src, *pp_item);
1576*d6b92ffaSHans Petter Selasky p_temp = cl_fmap_insert(p_dest, cl_fmap_key(*pp_item), *pp_item);
1577*d6b92ffaSHans Petter Selasky /* We should never have duplicates. */
1578*d6b92ffaSHans Petter Selasky CL_ASSERT(p_temp == *pp_item);
1579*d6b92ffaSHans Petter Selasky /* Point pp_item to a valid item in the source map. */
1580*d6b92ffaSHans Petter Selasky (*pp_item) = p_next;
1581*d6b92ffaSHans Petter Selasky }
1582*d6b92ffaSHans Petter Selasky
cl_fmap_delta(IN OUT cl_fmap_t * const p_map1,IN OUT cl_fmap_t * const p_map2,OUT cl_fmap_t * const p_new,OUT cl_fmap_t * const p_old)1583*d6b92ffaSHans Petter Selasky void cl_fmap_delta(IN OUT cl_fmap_t * const p_map1,
1584*d6b92ffaSHans Petter Selasky IN OUT cl_fmap_t * const p_map2,
1585*d6b92ffaSHans Petter Selasky OUT cl_fmap_t * const p_new, OUT cl_fmap_t * const p_old)
1586*d6b92ffaSHans Petter Selasky {
1587*d6b92ffaSHans Petter Selasky cl_fmap_item_t *p_item1, *p_item2;
1588*d6b92ffaSHans Petter Selasky int cmp;
1589*d6b92ffaSHans Petter Selasky
1590*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map1);
1591*d6b92ffaSHans Petter Selasky CL_ASSERT(p_map2);
1592*d6b92ffaSHans Petter Selasky CL_ASSERT(p_new);
1593*d6b92ffaSHans Petter Selasky CL_ASSERT(p_old);
1594*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_fmap_empty(p_new));
1595*d6b92ffaSHans Petter Selasky CL_ASSERT(cl_is_fmap_empty(p_old));
1596*d6b92ffaSHans Petter Selasky
1597*d6b92ffaSHans Petter Selasky p_item1 = cl_fmap_head(p_map1);
1598*d6b92ffaSHans Petter Selasky p_item2 = cl_fmap_head(p_map2);
1599*d6b92ffaSHans Petter Selasky
1600*d6b92ffaSHans Petter Selasky while (p_item1 != cl_fmap_end(p_map1) && p_item2 != cl_fmap_end(p_map2)) {
1601*d6b92ffaSHans Petter Selasky cmp = p_map1->pfn_compare(cl_fmap_key(p_item1),
1602*d6b92ffaSHans Petter Selasky cl_fmap_key(p_item2));
1603*d6b92ffaSHans Petter Selasky if (cmp < 0) {
1604*d6b92ffaSHans Petter Selasky /* We found an old item. */
1605*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_old, p_map1, &p_item1);
1606*d6b92ffaSHans Petter Selasky } else if (cmp > 0) {
1607*d6b92ffaSHans Petter Selasky /* We found a new item. */
1608*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_new, p_map2, &p_item2);
1609*d6b92ffaSHans Petter Selasky } else {
1610*d6b92ffaSHans Petter Selasky /* Move both forward since they have the same key. */
1611*d6b92ffaSHans Petter Selasky p_item1 = cl_fmap_next(p_item1);
1612*d6b92ffaSHans Petter Selasky p_item2 = cl_fmap_next(p_item2);
1613*d6b92ffaSHans Petter Selasky }
1614*d6b92ffaSHans Petter Selasky }
1615*d6b92ffaSHans Petter Selasky
1616*d6b92ffaSHans Petter Selasky /* Process the remainder if the end of either source map was reached. */
1617*d6b92ffaSHans Petter Selasky while (p_item2 != cl_fmap_end(p_map2))
1618*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_new, p_map2, &p_item2);
1619*d6b92ffaSHans Petter Selasky
1620*d6b92ffaSHans Petter Selasky while (p_item1 != cl_fmap_end(p_map1))
1621*d6b92ffaSHans Petter Selasky __cl_fmap_delta_move(p_old, p_map1, &p_item1);
1622*d6b92ffaSHans Petter Selasky }
1623