exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / gl_map.h
blobd072fdd022c2aa011df3b50c92670a59ef959d1a
1 /* Abstract map data type.
2 Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2018.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 #ifndef _GL_MAP_H
19 #define _GL_MAP_H
21 /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE,
22 _GL_ATTRIBUTE_NODISCARD. */
23 #if !_GL_CONFIG_H_INCLUDED
24 #error "Please include config.h first."
25 #endif
27 #include <stddef.h>
29 _GL_INLINE_HEADER_BEGIN
30 #ifndef GL_MAP_INLINE
31 # define GL_MAP_INLINE _GL_INLINE
32 #endif
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
39 /* gl_map is an abstract map data type. It can contain any number of
40 (key, value) pairs, where
41 - keys and values are objects ('void *' or 'const void *' pointers),
42 - There are no (key, value1) and (key, value2) pairs with the same key
43 (in the sense of a given comparator function).
45 There are several implementations of this map datatype, optimized for
46 different operations or for memory. You can start using the simplest map
47 implementation, GL_ARRAY_MAP, and switch to a different implementation
48 later, when you realize which operations are performed the most frequently.
49 The API of the different implementations is exactly the same; when switching
50 to a different implementation, you only have to change the gl_map_create
51 call.
53 The implementations are:
54 GL_ARRAY_MAP a growable array
55 GL_LINKEDHASH_MAP a hash table with a linked list
56 GL_HASH_MAP a hash table
58 The memory consumption is asymptotically the same: O(1) for every pair
59 in the map. When looking more closely at the average memory consumed
60 for an object, GL_ARRAY_MAP is the most compact representation, then comes
61 GL_HASH_MAP, and GL_LINKEDHASH_MAP needs the most memory.
63 The guaranteed average performance of the operations is, for a map of
64 n pairs:
66 Operation ARRAY LINKEDHASH
67 HASH
69 gl_map_size O(1) O(1)
70 gl_map_get O(n) O(1)
71 gl_map_put O(n) O(1)
72 gl_map_remove O(n) O(1)
73 gl_map_search O(n) O(1)
74 gl_map_iterator O(1) O(1)
75 gl_map_iterator_next O(1) O(1)
78 /* --------------------------- gl_map_t Data Type --------------------------- */
80 /* Type of function used to compare two keys.
81 NULL denotes pointer comparison. */
82 typedef bool (*gl_mapkey_equals_fn) (const void *key1, const void *key2);
84 /* Type of function used to compute a hash code.
85 NULL denotes a function that depends only on the pointer itself. */
86 typedef size_t (*gl_mapkey_hashcode_fn) (const void *key);
88 #ifndef _GL_MAP_DISPOSE_FNS_DEFINED
90 /* Type of function used to dispose a key once a (key, value) pair is removed
91 from a map. NULL denotes a no-op. */
92 typedef void (*gl_mapkey_dispose_fn) (const void *key);
94 /* Type of function used to dispose a value once a (key, value) pair is removed
95 from a map. NULL denotes a no-op. */
96 typedef void (*gl_mapvalue_dispose_fn) (const void *value);
98 # define _GL_MAP_DISPOSE_FNS_DEFINED 1
99 #endif
101 struct gl_map_impl;
102 /* Type representing an entire map. */
103 typedef struct gl_map_impl * gl_map_t;
105 struct gl_map_implementation;
106 /* Type representing a map datatype implementation. */
107 typedef const struct gl_map_implementation * gl_map_implementation_t;
109 #if 0 /* Unless otherwise specified, these are defined inline below. */
111 /* Creates an empty map.
112 IMPLEMENTATION is one of GL_ARRAY_MAP, GL_LINKEDHASH_MAP, GL_HASH_MAP.
113 EQUALS_FN is a key comparison function or NULL.
114 HASHCODE_FN is a key hash code function or NULL.
115 KDISPOSE_FN is a key disposal function or NULL.
116 VDISPOSE_FN is a value disposal function or NULL. */
117 /* declared in gl_xmap.h */
118 extern gl_map_t gl_map_create_empty (gl_map_implementation_t implementation,
119 gl_mapkey_equals_fn equals_fn,
120 gl_mapkey_hashcode_fn hashcode_fn,
121 gl_mapkey_dispose_fn kdispose_fn,
122 gl_mapvalue_dispose_fn vdispose_fn)
123 /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/
124 _GL_ATTRIBUTE_RETURNS_NONNULL;
125 /* Likewise. Returns NULL upon out-of-memory. */
126 extern gl_map_t gl_map_nx_create_empty (gl_map_implementation_t implementation,
127 gl_mapkey_equals_fn equals_fn,
128 gl_mapkey_hashcode_fn hashcode_fn,
129 gl_mapkey_dispose_fn kdispose_fn,
130 gl_mapvalue_dispose_fn vdispose_fn)
131 /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/;
133 /* Returns the current number of pairs in a map. */
134 extern size_t gl_map_size (gl_map_t map);
136 /* Searches whether a pair with the given key is already in the map.
137 Returns the value if found, or NULL if not present in the map. */
138 extern const void * gl_map_get (gl_map_t map, const void *key);
140 /* Searches whether a pair with the given key is already in the map.
141 Returns true and sets *VALUEP to the value if found.
142 Returns false if not present in the map. */
143 extern bool gl_map_search (gl_map_t map, const void *key, const void **valuep);
145 /* Adds a pair to a map.
146 Returns true if a pair with the given key was not already in the map and so
147 this pair was added.
148 Returns false if a pair with the given key was already in the map and only
149 its value was replaced. */
150 /* declared in gl_xmap.h */
151 extern bool gl_map_put (gl_map_t map, const void *key, const void *value);
152 /* Likewise. Returns -1 upon out-of-memory. */
153 _GL_ATTRIBUTE_NODISCARD
154 extern int gl_map_nx_put (gl_map_t map, const void *key, const void *value);
156 /* Adds a pair to a map and retrieves the previous value.
157 Returns true if a pair with the given key was not already in the map and so
158 this pair was added.
159 Returns false and sets *OLDVALUEP to the previous value, if a pair with the
160 given key was already in the map and only its value was replaced. */
161 /* declared in gl_xmap.h */
162 extern bool gl_map_getput (gl_map_t map, const void *key, const void *value,
163 const void **oldvaluep);
164 /* Likewise. Returns -1 upon out-of-memory. */
165 _GL_ATTRIBUTE_NODISCARD
166 extern int gl_map_nx_getput (gl_map_t map, const void *key, const void *value,
167 const void **oldvaluep);
169 /* Removes a pair from a map.
170 Returns true if the key was found and its pair removed.
171 Returns false otherwise. */
172 extern bool gl_map_remove (gl_map_t map, const void *key);
174 /* Removes a pair from a map and retrieves the previous value.
175 Returns true and sets *OLDVALUEP to the previous value, if the key was found
176 and its pair removed.
177 Returns false otherwise. */
178 extern bool gl_map_getremove (gl_map_t map, const void *key,
179 const void **oldvaluep);
181 /* Frees an entire map.
182 (But this call does not free the keys and values of the pairs in the map.
183 It only invokes the KDISPOSE_FN on each key and the VDISPOSE_FN on each value
184 of the pairs in the map.) */
185 extern void gl_map_free (gl_map_t map);
187 #endif /* End of inline and gl_xmap.h-defined functions. */
189 /* ---------------------- gl_map_iterator_t Data Type ---------------------- */
191 /* Functions for iterating through a map.
192 Note: Iterating through a map of type GL_HASH_MAP returns the pairs in an
193 unpredictable order. If you need a predictable order, use GL_LINKEDHASH_MAP
194 instead of GL_HASH_MAP. */
196 /* Type of an iterator that traverses a map.
197 This is a fixed-size struct, so that creation of an iterator doesn't need
198 memory allocation on the heap. */
199 typedef struct
201 /* For fast dispatch of gl_map_iterator_next. */
202 const struct gl_map_implementation *vtable;
203 /* For detecting whether the last returned pair was removed. */
204 gl_map_t map;
205 size_t count;
206 /* Other, implementation-private fields. */
207 void *p; void *q;
208 size_t i; size_t j;
209 } gl_map_iterator_t;
211 #if 0 /* These are defined inline below. */
213 /* Creates an iterator traversing a map.
214 The map's contents must not be modified while the iterator is in use,
215 except for modifying the value of the last returned key or removing the
216 last returned pair. */
217 extern gl_map_iterator_t gl_map_iterator (gl_map_t map);
219 /* If there is a next pair, stores the next pair in *KEYP and *VALUEP, advances
220 the iterator, and returns true. Otherwise, returns false. */
221 extern bool gl_map_iterator_next (gl_map_iterator_t *iterator,
222 const void **keyp, const void **valuep);
224 /* Frees an iterator. */
225 extern void gl_map_iterator_free (gl_map_iterator_t *iterator);
227 #endif /* End of inline functions. */
229 /* ------------------------- Implementation Details ------------------------- */
231 struct gl_map_implementation
233 /* gl_map_t functions. */
234 gl_map_t (*nx_create_empty) (gl_map_implementation_t implementation,
235 gl_mapkey_equals_fn equals_fn,
236 gl_mapkey_hashcode_fn hashcode_fn,
237 gl_mapkey_dispose_fn kdispose_fn,
238 gl_mapvalue_dispose_fn vdispose_fn);
239 size_t (*size) (gl_map_t map);
240 bool (*search) (gl_map_t map, const void *key, const void **valuep);
241 int (*nx_getput) (gl_map_t map, const void *key, const void *value,
242 const void **oldvaluep);
243 bool (*getremove) (gl_map_t map, const void *key, const void **oldvaluep);
244 void (*map_free) (gl_map_t map);
245 /* gl_map_iterator_t functions. */
246 gl_map_iterator_t (*iterator) (gl_map_t map);
247 bool (*iterator_next) (gl_map_iterator_t *iterator,
248 const void **keyp, const void **valuep);
249 void (*iterator_free) (gl_map_iterator_t *iterator);
252 struct gl_map_impl_base
254 const struct gl_map_implementation *vtable;
255 gl_mapkey_equals_fn equals_fn;
256 gl_mapkey_dispose_fn kdispose_fn;
257 gl_mapvalue_dispose_fn vdispose_fn;
260 /* Define most functions of this file as accesses to the
261 struct gl_map_implementation. */
263 GL_MAP_INLINE
264 /*_GL_ATTRIBUTE_DEALLOC (gl_map_free, 1)*/
265 gl_map_t
266 gl_map_nx_create_empty (gl_map_implementation_t implementation,
267 gl_mapkey_equals_fn equals_fn,
268 gl_mapkey_hashcode_fn hashcode_fn,
269 gl_mapkey_dispose_fn kdispose_fn,
270 gl_mapvalue_dispose_fn vdispose_fn)
272 return implementation->nx_create_empty (implementation,
273 equals_fn, hashcode_fn,
274 kdispose_fn, vdispose_fn);
277 GL_MAP_INLINE size_t
278 gl_map_size (gl_map_t map)
280 return ((const struct gl_map_impl_base *) map)->vtable->size (map);
283 GL_MAP_INLINE bool
284 gl_map_search (gl_map_t map, const void *key, const void **valuep)
286 return ((const struct gl_map_impl_base *) map)->vtable
287 ->search (map, key, valuep);
290 _GL_ATTRIBUTE_NODISCARD GL_MAP_INLINE int
291 gl_map_nx_getput (gl_map_t map, const void *key, const void *value,
292 const void **oldvaluep)
294 return ((const struct gl_map_impl_base *) map)->vtable
295 ->nx_getput (map, key, value, oldvaluep);
298 GL_MAP_INLINE bool
299 gl_map_getremove (gl_map_t map, const void *key, const void **oldvaluep)
301 return ((const struct gl_map_impl_base *) map)->vtable
302 ->getremove (map, key, oldvaluep);
305 GL_MAP_INLINE void
306 gl_map_free (gl_map_t map)
308 ((const struct gl_map_impl_base *) map)->vtable->map_free (map);
311 GL_MAP_INLINE gl_map_iterator_t
312 gl_map_iterator (gl_map_t map)
314 return ((const struct gl_map_impl_base *) map)->vtable->iterator (map);
317 GL_MAP_INLINE bool
318 gl_map_iterator_next (gl_map_iterator_t *iterator,
319 const void **keyp, const void **valuep)
321 return iterator->vtable->iterator_next (iterator, keyp, valuep);
324 GL_MAP_INLINE void
325 gl_map_iterator_free (gl_map_iterator_t *iterator)
327 iterator->vtable->iterator_free (iterator);
330 /* Define the convenience functions, that is, the functions that are independent
331 of the implementation. */
333 GL_MAP_INLINE const void *
334 gl_map_get (gl_map_t map, const void *key)
336 const void *value = NULL;
337 gl_map_search (map, key, &value);
338 return value;
341 _GL_ATTRIBUTE_NODISCARD GL_MAP_INLINE int
342 gl_map_nx_put (gl_map_t map, const void *key, const void *value)
344 const void *oldvalue;
345 int result = gl_map_nx_getput (map, key, value, &oldvalue);
346 if (result == 0)
348 gl_mapvalue_dispose_fn vdispose_fn =
349 ((const struct gl_map_impl_base *) map)->vdispose_fn;
350 if (vdispose_fn != NULL)
351 vdispose_fn (oldvalue);
353 return result;
356 GL_MAP_INLINE bool
357 gl_map_remove (gl_map_t map, const void *key)
359 const void *oldvalue;
360 bool result = gl_map_getremove (map, key, &oldvalue);
361 if (result)
363 gl_mapvalue_dispose_fn vdispose_fn =
364 ((const struct gl_map_impl_base *) map)->vdispose_fn;
365 if (vdispose_fn != NULL)
366 vdispose_fn (oldvalue);
368 return result;
371 #ifdef __cplusplus
373 #endif
375 _GL_INLINE_HEADER_END
377 #endif /* _GL_MAP_H */