Line | Count | Source (jump to first uncovered line) |
1 | | /*====================================================================* |
2 | | - Copyright (C) 2001 Leptonica. All rights reserved. |
3 | | - |
4 | | - Redistribution and use in source and binary forms, with or without |
5 | | - modification, are permitted provided that the following conditions |
6 | | - are met: |
7 | | - 1. Redistributions of source code must retain the above copyright |
8 | | - notice, this list of conditions and the following disclaimer. |
9 | | - 2. Redistributions in binary form must reproduce the above |
10 | | - copyright notice, this list of conditions and the following |
11 | | - disclaimer in the documentation and/or other materials |
12 | | - provided with the distribution. |
13 | | - |
14 | | - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
15 | | - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
16 | | - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
17 | | - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY |
18 | | - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | | - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | | - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | | - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | | - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
23 | | - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
24 | | - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | | *====================================================================*/ |
26 | | |
27 | | /*! |
28 | | * \file map.c |
29 | | * <pre> |
30 | | * |
31 | | * This is an interface for map and set functions, based on using |
32 | | * red-black binary search trees. Because these trees are sorted, |
33 | | * they are O(nlogn) to build. They allow logn insertion, find |
34 | | * and deletion of elements. |
35 | | * |
36 | | * Both the map and set are ordered by key value, with unique keys. |
37 | | * For the map, the elements are key/value pairs. |
38 | | * For the set we only store unique, ordered keys, and the value |
39 | | * (set to 0 in the implementation) is ignored. |
40 | | * |
41 | | * The keys for the map and set can be any of the three types in the |
42 | | * l_rbtree_keytype enum. The values stored can be any of the four |
43 | | * types in the rb_type union. |
44 | | * |
45 | | * In-order forward and reverse iterators are provided for maps and sets. |
46 | | * To forward iterate over the map for any type of key (in this example, |
47 | | * uint32), extracting integer values: |
48 | | * |
49 | | * L_AMAP *m = l_amapCreate(L_UINT_TYPE); |
50 | | * [add elements to the map ...] |
51 | | * L_AMAP_NODE *n = l_amapGetFirst(m); |
52 | | * while (n) { |
53 | | * l_int32 val = n->value.itype; |
54 | | * // do something ... |
55 | | * n = l_amapGetNext(n); |
56 | | * } |
57 | | * |
58 | | * If the nodes are deleted during the iteration: |
59 | | * |
60 | | * L_AMAP *m = l_amapCreate(L_UINT_TYPE); |
61 | | * [add elements to the map ...] |
62 | | * L_AMAP_NODE *n = l_amapGetFirst(m); |
63 | | * L_AMAP_NODE *nn; |
64 | | * while (n) { |
65 | | * nn = l_amapGetNext(n); |
66 | | * l_int32 val = n->value.itype; |
67 | | * l_uint32 key = n->key.utype; |
68 | | * // do something ... |
69 | | * l_amapDelete(m, n->key); |
70 | | * n = nn; |
71 | | * } |
72 | | * |
73 | | * See prog/maptest.c and prog/settest.c for more examples of usage. |
74 | | * |
75 | | * Interface to (a) map using a general key and storing general values |
76 | | * L_AMAP *l_amapCreate() |
77 | | * RB_TYPE *l_amapFind() |
78 | | * void l_amapInsert() |
79 | | * void l_amapDelete() |
80 | | * void l_amapDestroy() |
81 | | * L_AMAP_NODE *l_amapGetFirst() |
82 | | * L_AMAP_NODE *l_amapGetNext() |
83 | | * L_AMAP_NODE *l_amapGetLast() |
84 | | * L_AMAP_NODE *l_amapGetPrev() |
85 | | * l_int32 l_amapSize() |
86 | | * |
87 | | * Interface to (a) set using a general key |
88 | | * L_ASET *l_asetCreate() |
89 | | * RB_TYPE *l_asetFind() |
90 | | * void l_asetInsert() |
91 | | * void l_asetDelete() |
92 | | * void l_asetDestroy() |
93 | | * L_ASET_NODE *l_asetGetFirst() |
94 | | * L_ASET_NODE *l_asetGetNext() |
95 | | * L_ASET_NODE *l_asetGetLast() |
96 | | * L_ASET_NODE *l_asetGetPrev() |
97 | | * l_int32 l_asetSize() |
98 | | * </pre> |
99 | | */ |
100 | | |
101 | | #ifdef HAVE_CONFIG_H |
102 | | #include <config_auto.h> |
103 | | #endif /* HAVE_CONFIG_H */ |
104 | | |
105 | | #include "allheaders.h" |
106 | | |
107 | | /* ------------------------------------------------------------- * |
108 | | * Interface to Map * |
109 | | * ------------------------------------------------------------- */ |
110 | | L_AMAP * |
111 | | l_amapCreate(l_int32 keytype) |
112 | 0 | { |
113 | 0 | L_AMAP *m; |
114 | |
|
115 | 0 | if (keytype != L_INT_TYPE && keytype != L_UINT_TYPE && |
116 | 0 | keytype != L_FLOAT_TYPE) |
117 | 0 | return (L_AMAP *)ERROR_PTR("invalid keytype", __func__, NULL); |
118 | | |
119 | 0 | m = (L_AMAP *)LEPT_CALLOC(1, sizeof(L_AMAP)); |
120 | 0 | m->keytype = keytype; |
121 | 0 | return m; |
122 | 0 | } |
123 | | |
124 | | RB_TYPE * |
125 | | l_amapFind(L_AMAP *m, |
126 | | RB_TYPE key) |
127 | 0 | { |
128 | 0 | return l_rbtreeLookup(m, key); |
129 | 0 | } |
130 | | |
131 | | void |
132 | | l_amapInsert(L_AMAP *m, |
133 | | RB_TYPE key, |
134 | | RB_TYPE value) |
135 | 0 | { |
136 | 0 | l_rbtreeInsert(m, key, value); |
137 | 0 | } |
138 | | |
139 | | void |
140 | | l_amapDelete(L_AMAP *m, |
141 | | RB_TYPE key) |
142 | 0 | { |
143 | 0 | l_rbtreeDelete(m, key); |
144 | 0 | } |
145 | | |
146 | | void |
147 | | l_amapDestroy(L_AMAP **pm) |
148 | 0 | { |
149 | 0 | l_rbtreeDestroy(pm); |
150 | 0 | } |
151 | | |
152 | | L_AMAP_NODE * |
153 | | l_amapGetFirst(L_AMAP *m) |
154 | 0 | { |
155 | 0 | return l_rbtreeGetFirst(m); |
156 | 0 | } |
157 | | |
158 | | L_AMAP_NODE * |
159 | | l_amapGetNext(L_AMAP_NODE *n) |
160 | 0 | { |
161 | 0 | return l_rbtreeGetNext(n); |
162 | 0 | } |
163 | | |
164 | | L_AMAP_NODE * |
165 | | l_amapGetLast(L_AMAP *m) |
166 | 0 | { |
167 | 0 | return l_rbtreeGetLast(m); |
168 | 0 | } |
169 | | |
170 | | L_AMAP_NODE * |
171 | | l_amapGetPrev(L_AMAP_NODE *n) |
172 | 0 | { |
173 | 0 | return l_rbtreeGetPrev(n); |
174 | 0 | } |
175 | | |
176 | | l_int32 |
177 | | l_amapSize(L_AMAP *m) |
178 | 0 | { |
179 | 0 | return l_rbtreeGetCount(m); |
180 | 0 | } |
181 | | |
182 | | |
183 | | /* ------------------------------------------------------------- * |
184 | | * Interface to Set * |
185 | | * ------------------------------------------------------------- */ |
186 | | L_ASET * |
187 | | l_asetCreate(l_int32 keytype) |
188 | 0 | { |
189 | 0 | L_ASET *s; |
190 | |
|
191 | 0 | if (keytype != L_INT_TYPE && keytype != L_UINT_TYPE && |
192 | 0 | keytype != L_FLOAT_TYPE) |
193 | 0 | return (L_ASET *)ERROR_PTR("invalid keytype", __func__, NULL); |
194 | | |
195 | 0 | s = (L_ASET *)LEPT_CALLOC(1, sizeof(L_ASET)); |
196 | 0 | s->keytype = keytype; |
197 | 0 | return s; |
198 | 0 | } |
199 | | |
200 | | /* |
201 | | * l_asetFind() |
202 | | * |
203 | | * This returns NULL if not found, non-null if it is. In the latter |
204 | | * case, the value stored in the returned pointer has no significance. |
205 | | */ |
206 | | RB_TYPE * |
207 | | l_asetFind(L_ASET *s, |
208 | | RB_TYPE key) |
209 | 0 | { |
210 | 0 | return l_rbtreeLookup(s, key); |
211 | 0 | } |
212 | | |
213 | | void |
214 | | l_asetInsert(L_ASET *s, |
215 | | RB_TYPE key) |
216 | 0 | { |
217 | 0 | RB_TYPE value; |
218 | |
|
219 | 0 | value.itype = 0; /* meaningless */ |
220 | 0 | l_rbtreeInsert(s, key, value); |
221 | 0 | } |
222 | | |
223 | | void |
224 | | l_asetDelete(L_ASET *s, |
225 | | RB_TYPE key) |
226 | 0 | { |
227 | 0 | l_rbtreeDelete(s, key); |
228 | 0 | } |
229 | | |
230 | | void |
231 | | l_asetDestroy(L_ASET **ps) |
232 | 0 | { |
233 | 0 | l_rbtreeDestroy(ps); |
234 | 0 | } |
235 | | |
236 | | L_ASET_NODE * |
237 | | l_asetGetFirst(L_ASET *s) |
238 | 0 | { |
239 | 0 | return l_rbtreeGetFirst(s); |
240 | 0 | } |
241 | | |
242 | | L_ASET_NODE * |
243 | | l_asetGetNext(L_ASET_NODE *n) |
244 | 0 | { |
245 | 0 | return l_rbtreeGetNext(n); |
246 | 0 | } |
247 | | |
248 | | L_ASET_NODE * |
249 | | l_asetGetLast(L_ASET *s) |
250 | 0 | { |
251 | 0 | return l_rbtreeGetLast(s); |
252 | 0 | } |
253 | | |
254 | | L_ASET_NODE * |
255 | | l_asetGetPrev(L_ASET_NODE *n) |
256 | 0 | { |
257 | 0 | return l_rbtreeGetPrev(n); |
258 | 0 | } |
259 | | |
260 | | l_int32 |
261 | | l_asetSize(L_ASET *s) |
262 | 0 | { |
263 | 0 | return l_rbtreeGetCount(s); |
264 | 0 | } |