exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / gl_set.h
blob51d7fae1a20df18c7967e71e61cbc0381e068f4b
1 /* Abstract set 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_SET_H
19 #define _GL_SET_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_SET_INLINE
31 # define GL_SET_INLINE _GL_INLINE
32 #endif
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
39 /* gl_set is an abstract set data type. It can contain any number of objects
40 ('void *' or 'const void *' pointers); the order does not matter.
41 Duplicates (in the sense of the comparator) are forbidden.
43 There are several implementations of this set datatype, optimized for
44 different operations or for memory. You can start using the simplest set
45 implementation, GL_ARRAY_SET, and switch to a different implementation
46 later, when you realize which operations are performed the most frequently.
47 The API of the different implementations is exactly the same; when switching
48 to a different implementation, you only have to change the gl_set_create
49 call.
51 The implementations are:
52 GL_ARRAY_SET a growable array
53 GL_LINKEDHASH_SET a hash table with a linked list
54 GL_HASH_SET a hash table
56 The memory consumption is asymptotically the same: O(1) for every object
57 in the set. When looking more closely at the average memory consumed
58 for an object, GL_ARRAY_SET is the most compact representation, then comes
59 GL_HASH_SET, and GL_LINKEDHASH_SET needs the most memory.
61 The guaranteed average performance of the operations is, for a set of
62 n elements:
64 Operation ARRAY LINKEDHASH
65 HASH
67 gl_set_size O(1) O(1)
68 gl_set_add O(n) O(1)
69 gl_set_remove O(n) O(1)
70 gl_set_search O(n) O(1)
71 gl_set_iterator O(1) O(1)
72 gl_set_iterator_next O(1) O(1)
75 /* --------------------------- gl_set_t Data Type --------------------------- */
77 /* Type of function used to compare two elements.
78 NULL denotes pointer comparison. */
79 typedef bool (*gl_setelement_equals_fn) (const void *elt1, const void *elt2);
81 /* Type of function used to compute a hash code.
82 NULL denotes a function that depends only on the pointer itself. */
83 typedef size_t (*gl_setelement_hashcode_fn) (const void *elt);
85 #ifndef _GL_SETELEMENT_DISPOSE_FN_DEFINED
86 /* Type of function used to dispose an element once it's removed from a set.
87 NULL denotes a no-op. */
88 typedef void (*gl_setelement_dispose_fn) (const void *elt);
89 # define _GL_SETELEMENT_DISPOSE_FN_DEFINED 1
90 #endif
92 struct gl_set_impl;
93 /* Type representing an entire set. */
94 typedef struct gl_set_impl * gl_set_t;
96 struct gl_set_implementation;
97 /* Type representing a set datatype implementation. */
98 typedef const struct gl_set_implementation * gl_set_implementation_t;
100 #if 0 /* Unless otherwise specified, these are defined inline below. */
102 /* Creates an empty set.
103 IMPLEMENTATION is one of GL_ARRAY_SET, GL_LINKEDHASH_SET, GL_HASH_SET.
104 EQUALS_FN is an element comparison function or NULL.
105 HASHCODE_FN is an element hash code function or NULL.
106 DISPOSE_FN is an element disposal function or NULL. */
107 /* declared in gl_xset.h */
108 extern gl_set_t gl_set_create_empty (gl_set_implementation_t implementation,
109 gl_setelement_equals_fn equals_fn,
110 gl_setelement_hashcode_fn hashcode_fn,
111 gl_setelement_dispose_fn dispose_fn)
112 /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/
113 _GL_ATTRIBUTE_RETURNS_NONNULL;
114 /* Likewise. Returns NULL upon out-of-memory. */
115 extern gl_set_t gl_set_nx_create_empty (gl_set_implementation_t implementation,
116 gl_setelement_equals_fn equals_fn,
117 gl_setelement_hashcode_fn hashcode_fn,
118 gl_setelement_dispose_fn dispose_fn)
119 /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/;
121 /* Returns the current number of elements in a set. */
122 extern size_t gl_set_size (gl_set_t set);
124 /* Searches whether an element is already in the set.
125 Returns true if found, or false if not present in the set. */
126 extern bool gl_set_search (gl_set_t set, const void *elt);
128 /* Adds an element to a set.
129 Returns true if it was not already in the set and added, false otherwise. */
130 /* declared in gl_xset.h */
131 extern bool gl_set_add (gl_set_t set, const void *elt);
133 /* Likewise. Returns -1 upon out-of-memory. */
134 _GL_ATTRIBUTE_NODISCARD
135 extern int gl_set_nx_add (gl_set_t set, const void *elt);
137 /* Removes an element from a set.
138 Returns true if it was found and removed. */
139 extern bool gl_set_remove (gl_set_t set, const void *elt);
141 /* Frees an entire set.
142 (But this call does not free the elements of the set. It only invokes
143 the DISPOSE_FN on each of the elements of the set.) */
144 extern void gl_set_free (gl_set_t set);
146 #endif /* End of inline and gl_xset.h-defined functions. */
148 /* ---------------------- gl_set_iterator_t Data Type ---------------------- */
150 /* Functions for iterating through a set.
151 Note: Iterating through a set of type GL_HASH_SET returns the elements in an
152 unpredictable order. If you need a predictable order, use GL_LINKEDHASH_SET
153 instead of GL_HASH_SET. */
155 /* Type of an iterator that traverses a set.
156 This is a fixed-size struct, so that creation of an iterator doesn't need
157 memory allocation on the heap. */
158 typedef struct
160 /* For fast dispatch of gl_set_iterator_next. */
161 const struct gl_set_implementation *vtable;
162 /* For detecting whether the last returned element was removed. */
163 gl_set_t set;
164 size_t count;
165 /* Other, implementation-private fields. */
166 void *p; void *q;
167 size_t i; size_t j;
168 } gl_set_iterator_t;
170 #if 0 /* These are defined inline below. */
172 /* Creates an iterator traversing a set.
173 The set's contents must not be modified while the iterator is in use,
174 except for removing the last returned element. */
175 extern gl_set_iterator_t gl_set_iterator (gl_set_t set);
177 /* If there is a next element, stores the next element in *ELTP, advances the
178 iterator and returns true. Otherwise, returns false. */
179 extern bool gl_set_iterator_next (gl_set_iterator_t *iterator,
180 const void **eltp);
182 /* Frees an iterator. */
183 extern void gl_set_iterator_free (gl_set_iterator_t *iterator);
185 #endif /* End of inline functions. */
187 /* ------------------------ Implementation Details ------------------------ */
189 struct gl_set_implementation
191 /* gl_set_t functions. */
192 gl_set_t (*nx_create_empty) (gl_set_implementation_t implementation,
193 gl_setelement_equals_fn equals_fn,
194 gl_setelement_hashcode_fn hashcode_fn,
195 gl_setelement_dispose_fn dispose_fn);
196 size_t (*size) (gl_set_t set);
197 bool (*search) (gl_set_t set, const void *elt);
198 int (*nx_add) (gl_set_t set, const void *elt);
199 bool (*remove_elt) (gl_set_t set, const void *elt);
200 void (*set_free) (gl_set_t set);
201 /* gl_set_iterator_t functions. */
202 gl_set_iterator_t (*iterator) (gl_set_t set);
203 bool (*iterator_next) (gl_set_iterator_t *iterator, const void **eltp);
204 void (*iterator_free) (gl_set_iterator_t *iterator);
207 struct gl_set_impl_base
209 const struct gl_set_implementation *vtable;
210 gl_setelement_equals_fn equals_fn;
211 gl_setelement_dispose_fn dispose_fn;
214 /* Define all functions of this file as accesses to the
215 struct gl_set_implementation. */
217 GL_SET_INLINE
218 /*_GL_ATTRIBUTE_DEALLOC (gl_set_free, 1)*/
219 gl_set_t
220 gl_set_nx_create_empty (gl_set_implementation_t implementation,
221 gl_setelement_equals_fn equals_fn,
222 gl_setelement_hashcode_fn hashcode_fn,
223 gl_setelement_dispose_fn dispose_fn)
225 return implementation->nx_create_empty (implementation, equals_fn,
226 hashcode_fn, dispose_fn);
229 GL_SET_INLINE size_t
230 gl_set_size (gl_set_t set)
232 return ((const struct gl_set_impl_base *) set)->vtable->size (set);
235 GL_SET_INLINE bool
236 gl_set_search (gl_set_t set, const void *elt)
238 return ((const struct gl_set_impl_base *) set)->vtable->search (set, elt);
241 _GL_ATTRIBUTE_NODISCARD GL_SET_INLINE int
242 gl_set_nx_add (gl_set_t set, const void *elt)
244 return ((const struct gl_set_impl_base *) set)->vtable->nx_add (set, elt);
247 GL_SET_INLINE bool
248 gl_set_remove (gl_set_t set, const void *elt)
250 return ((const struct gl_set_impl_base *) set)->vtable->remove_elt (set, elt);
253 GL_SET_INLINE void
254 gl_set_free (gl_set_t set)
256 ((const struct gl_set_impl_base *) set)->vtable->set_free (set);
259 GL_SET_INLINE gl_set_iterator_t
260 gl_set_iterator (gl_set_t set)
262 return ((const struct gl_set_impl_base *) set)->vtable->iterator (set);
265 GL_SET_INLINE bool
266 gl_set_iterator_next (gl_set_iterator_t *iterator, const void **eltp)
268 return iterator->vtable->iterator_next (iterator, eltp);
271 GL_SET_INLINE void
272 gl_set_iterator_free (gl_set_iterator_t *iterator)
274 iterator->vtable->iterator_free (iterator);
277 #ifdef __cplusplus
279 #endif
281 _GL_INLINE_HEADER_END
283 #endif /* _GL_SET_H */