* verror.c: Include <config.h> unconditionally.
[gnulib.git] / lib / gl_oset.h
1 /* Abstract ordered set data type.
2    Copyright (C) 2006 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2006.
4
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 2, or (at your option)
8    any later version.
9
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.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19 #ifndef _GL_OSET_H
20 #define _GL_OSET_H
21
22 #include <stdbool.h>
23 #include <stddef.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29
30 /* gl_oset is an abstract ordered set data type.  It can contain any number
31    of objects ('void *' or 'const void *' pointers) in the order of a given
32    comparator function.  Duplicates (in the sense of the comparator) are
33    forbidden.
34
35    There are several implementations of this ordered set datatype, optimized
36    for different operations or for memory.  You can start using the simplest
37    ordered set implementation, GL_ARRAY_OSET, and switch to a different
38    implementation later, when you realize which operations are performed
39    the most frequently.  The API of the different implementations is exactly
40    the same; when switching to a different implementation, you only have to
41    change the gl_oset_create call.
42
43    The implementations are:
44      GL_ARRAY_OSET        a growable array
45      GL_AVLTREE_OSET      a binary tree (AVL tree)
46      GL_RBTREE_OSET       a binary tree (red-black tree)
47
48    The memory consumption is asymptotically the same: O(1) for every object
49    in the set.  When looking more closely at the average memory consumed
50    for an object, GL_ARRAY_OSET is the most compact representation, and
51    GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory.
52
53    The guaranteed average performance of the operations is, for a set of
54    n elements:
55
56    Operation                  ARRAY     TREE
57
58    gl_oset_size                O(1)     O(1)
59    gl_oset_add                 O(n)   O(log n)
60    gl_oset_remove              O(n)   O(log n)
61    gl_oset_search            O(log n) O(log n)
62    gl_oset_iterator            O(1)   O(log n)
63    gl_oset_iterator_next       O(1)   O(log n)
64  */
65
66 /* -------------------------- gl_oset_t Data Type -------------------------- */
67
68 /* Type of function used to compare two elements.  Same as for qsort().
69    NULL denotes pointer comparison.  */
70 typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2);
71
72 struct gl_oset_impl;
73 /* Type representing an entire ordered set.  */
74 typedef struct gl_oset_impl * gl_oset_t;
75
76 struct gl_oset_implementation;
77 /* Type representing a ordered set datatype implementation.  */
78 typedef const struct gl_oset_implementation * gl_oset_implementation_t;
79
80 /* Create an empty set.
81    IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET.
82    COMPAR_FN is an element comparison function or NULL.  */
83 extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation,
84                                        gl_setelement_compar_fn compar_fn);
85
86 /* Return the current number of elements in an ordered set.  */
87 extern size_t gl_oset_size (gl_oset_t set);
88
89 /* Search whether an element is already in the ordered set.
90    Return true if found, or false if not present in the set.  */
91 extern bool gl_oset_search (gl_oset_t set, const void *elt);
92
93 /* Add an element to an ordered set.
94    Return true if it was not already in the set and added.  */
95 extern bool gl_oset_add (gl_oset_t set, const void *elt);
96
97 /* Remove an element from an ordered set.
98    Return true if it was found and removed.  */
99 extern bool gl_oset_remove (gl_oset_t set, const void *elt);
100
101 /* Free an entire ordered set.
102    (But this call does not free the elements of the set.)  */
103 extern void gl_oset_free (gl_oset_t set);
104
105 /* --------------------- gl_oset_iterator_t Data Type --------------------- */
106
107 /* Functions for iterating through an ordered set.  */
108
109 /* Type of an iterator that traverses an ordered set.
110    This is a fixed-size struct, so that creation of an iterator doesn't need
111    memory allocation on the heap.  */
112 typedef struct
113 {
114   /* For fast dispatch of gl_oset_iterator_next.  */
115   const struct gl_oset_implementation *vtable;
116   /* For detecting whether the last returned element was removed.  */
117   gl_oset_t set;
118   size_t count;
119   /* Other, implementation-private fields.  */
120   void *p; void *q;
121   size_t i; size_t j;
122 } gl_oset_iterator_t;
123
124 /* Create an iterator traversing an ordered set.
125    The set's contents must not be modified while the iterator is in use,
126    except for removing the last returned element.  */
127 extern gl_oset_iterator_t gl_oset_iterator (gl_oset_t set);
128
129 /* If there is a next element, store the next element in *ELTP, advance the
130    iterator and return true.  Otherwise, return false.  */
131 extern bool gl_oset_iterator_next (gl_oset_iterator_t *iterator,
132                                    const void **eltp);
133
134 /* Free an iterator.  */
135 extern void gl_oset_iterator_free (gl_oset_iterator_t *iterator);
136
137 /* ------------------------ Implementation Details ------------------------ */
138
139 struct gl_oset_implementation
140 {
141   // gl_oset_t functions.
142   gl_oset_t (*create_empty) (gl_oset_implementation_t implementation,
143                              gl_setelement_compar_fn compar_fn);
144   size_t (*size) (gl_oset_t set);
145   bool (*search) (gl_oset_t set, const void *elt);
146   bool (*add) (gl_oset_t set, const void *elt);
147   bool (*remove) (gl_oset_t set, const void *elt);
148   void (*oset_free) (gl_oset_t set);
149   // gl_oset_iterator_t functions.
150   gl_oset_iterator_t (*iterator) (gl_oset_t set);
151   bool (*iterator_next) (gl_oset_iterator_t *iterator, const void **eltp);
152   void (*iterator_free) (gl_oset_iterator_t *iterator);
153 };
154
155 struct gl_oset_impl_base
156 {
157   const struct gl_oset_implementation *vtable;
158   gl_setelement_compar_fn compar_fn;
159 };
160
161 #if HAVE_INLINE
162
163 /* Define all functions of this file as inline accesses to the
164    struct gl_oset_implementation.
165    Use #define to avoid a warning because of extern vs. static.  */
166
167 # define gl_oset_create_empty gl_oset_create_empty_inline
168 static inline gl_oset_t
169 gl_oset_create_empty (gl_oset_implementation_t implementation,
170                       gl_setelement_compar_fn compar_fn)
171 {
172   return implementation->create_empty (implementation, compar_fn);
173 }
174
175 # define gl_oset_size gl_oset_size_inline
176 static inline size_t
177 gl_oset_size (gl_oset_t set)
178 {
179   return ((const struct gl_oset_impl_base *) set)->vtable->size (set);
180 }
181
182 # define gl_oset_search gl_oset_search_inline
183 static inline bool
184 gl_oset_search (gl_oset_t set, const void *elt)
185 {
186   return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt);
187 }
188
189 # define gl_oset_add gl_oset_add_inline
190 static inline bool
191 gl_oset_add (gl_oset_t set, const void *elt)
192 {
193   return ((const struct gl_oset_impl_base *) set)->vtable->add (set, elt);
194 }
195
196 # define gl_oset_remove gl_oset_remove_inline
197 static inline bool
198 gl_oset_remove (gl_oset_t set, const void *elt)
199 {
200   return ((const struct gl_oset_impl_base *) set)->vtable->remove (set, elt);
201 }
202
203 # define gl_oset_free gl_oset_free_inline
204 static inline void
205 gl_oset_free (gl_oset_t set)
206 {
207   ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set);
208 }
209
210 # define gl_oset_iterator gl_oset_iterator_inline
211 static inline gl_oset_iterator_t
212 gl_oset_iterator (gl_oset_t set)
213 {
214   return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set);
215 }
216
217 # define gl_oset_iterator_next gl_oset_iterator_next_inline
218 static inline bool
219 gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
220 {
221   return iterator->vtable->iterator_next (iterator, eltp);
222 }
223
224 # define gl_oset_iterator_free gl_oset_iterator_free_inline
225 static inline void
226 gl_oset_iterator_free (gl_oset_iterator_t *iterator)
227 {
228   iterator->vtable->iterator_free (iterator);
229 }
230
231 #endif
232
233 #ifdef __cplusplus
234 }
235 #endif
236
237 #endif /* _GL_OSET_H */