1 /* Abstract sequential list data type.  -*- coding: utf-8 -*-
2    Copyright (C) 2006-2019 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 3 of the License, or
8    (at your option) 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, see <https://www.gnu.org/licenses/>.  */
17 
18 #ifndef _GL_LIST_H
19 #define _GL_LIST_H
20 
21 #include <stdbool.h>
22 #include <stddef.h>
23 
24 #ifndef _GL_INLINE_HEADER_BEGIN
25  #error "Please include config.h first."
26 #endif
27 _GL_INLINE_HEADER_BEGIN
28 #ifndef GL_LIST_INLINE
29 # define GL_LIST_INLINE _GL_INLINE
30 #endif
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 
37 /* gl_list is an abstract list data type.  It can contain any number of
38    objects ('void *' or 'const void *' pointers) in any given order.
39    Duplicates are allowed, but can optionally be forbidden.
40 
41    There are several implementations of this list datatype, optimized for
42    different operations or for memory.  You can start using the simplest list
43    implementation, GL_ARRAY_LIST, and switch to a different implementation
44    later, when you realize which operations are performed the most frequently.
45    The API of the different implementations is exactly the same; when
46    switching to a different implementation, you only have to change the
47    gl_list_create call.
48 
49    The implementations are:
50      GL_ARRAY_LIST        a growable array
51      GL_CARRAY_LIST       a growable circular array
52      GL_LINKED_LIST       a linked list
53      GL_AVLTREE_LIST      a binary tree (AVL tree)
54      GL_RBTREE_LIST       a binary tree (red-black tree)
55      GL_LINKEDHASH_LIST   a hash table with a linked list
56      GL_AVLTREEHASH_LIST  a hash table with a binary tree (AVL tree)
57      GL_RBTREEHASH_LIST   a hash table with a binary tree (red-black tree)
58 
59    The memory consumption is asymptotically the same: O(1) for every object
60    in the list.  When looking more closely at the average memory consumed
61    for an object, GL_ARRAY_LIST is the most compact representation, and
62    GL_LINKEDHASH_LIST and GL_TREEHASH_LIST need more memory.
63 
64    The guaranteed average performance of the operations is, for a list of
65    n elements:
66 
67    Operation                  ARRAY    LINKED    TREE    LINKEDHASH   TREEHASH
68                               CARRAY                   with|without with|without
69                                                          duplicates  duplicates
70 
71    gl_list_size                O(1)     O(1)     O(1)      O(1)         O(1)
72    gl_list_node_value          O(1)     O(1)     O(1)      O(1)         O(1)
73    gl_list_node_set_value      O(1)     O(1)     O(1)      O(1)    O((log n)²)/O(1)
74    gl_list_next_node           O(1)     O(1)   O(log n)    O(1)       O(log n)
75    gl_list_previous_node       O(1)     O(1)   O(log n)    O(1)       O(log n)
76    gl_list_get_at              O(1)     O(n)   O(log n)    O(n)       O(log n)
77    gl_list_set_at              O(1)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
78    gl_list_search              O(n)     O(n)     O(n)    O(n)/O(1)    O(log n)/O(1)
79    gl_list_search_from         O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
80    gl_list_search_from_to      O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
81    gl_list_indexof             O(n)     O(n)     O(n)      O(n)       O(log n)
82    gl_list_indexof_from        O(n)     O(n)     O(n)      O(n)    O((log n)²)/O(log n)
83    gl_list_indexof_from_to     O(n)     O(n)     O(n)      O(n)    O((log n)²)/O(log n)
84    gl_list_add_first         O(n)/O(1)  O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
85    gl_list_add_last            O(1)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
86    gl_list_add_before          O(n)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
87    gl_list_add_after           O(n)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
88    gl_list_add_at              O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
89    gl_list_remove_node         O(n)     O(1)   O(log n)  O(n)/O(1) O((log n)²)/O(log n)
90    gl_list_remove_at           O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
91    gl_list_remove              O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
92    gl_list_iterator            O(1)     O(1)   O(log n)    O(1)       O(log n)
93    gl_list_iterator_from_to    O(1)     O(n)   O(log n)    O(n)       O(log n)
94    gl_list_iterator_next       O(1)     O(1)   O(log n)    O(1)       O(log n)
95    gl_sortedlist_search      O(log n)   O(n)   O(log n)    O(n)       O(log n)
96    gl_sortedlist_search_from O(log n)   O(n)   O(log n)    O(n)       O(log n)
97    gl_sortedlist_indexof     O(log n)   O(n)   O(log n)    O(n)       O(log n)
98    gl_sortedlist_indexof_fro O(log n)   O(n)   O(log n)    O(n)       O(log n)
99    gl_sortedlist_add           O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
100    gl_sortedlist_remove        O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
101  */
102 
103 /* -------------------------- gl_list_t Data Type -------------------------- */
104 
105 /* Type of function used to compare two elements.
106    NULL denotes pointer comparison.  */
107 typedef bool (*gl_listelement_equals_fn) (const void *elt1, const void *elt2);
108 
109 /* Type of function used to compute a hash code.
110    NULL denotes a function that depends only on the pointer itself.  */
111 typedef size_t (*gl_listelement_hashcode_fn) (const void *elt);
112 
113 /* Type of function used to dispose an element once it's removed from a list.
114    NULL denotes a no-op.  */
115 typedef void (*gl_listelement_dispose_fn) (const void *elt);
116 
117 struct gl_list_impl;
118 /* Type representing an entire list.  */
119 typedef struct gl_list_impl * gl_list_t;
120 
121 struct gl_list_node_impl;
122 /* Type representing the position of an element in the list, in a way that
123    is more adapted to the list implementation than a plain index.
124    Note: It is invalidated by insertions and removals!  */
125 typedef struct gl_list_node_impl * gl_list_node_t;
126 
127 struct gl_list_implementation;
128 /* Type representing a list datatype implementation.  */
129 typedef const struct gl_list_implementation * gl_list_implementation_t;
130 
131 #if 0 /* Unless otherwise specified, these are defined inline below.  */
132 
133 /* Create an empty list.
134    IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST,
135    GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST,
136    GL_RBTREEHASH_LIST.
137    EQUALS_FN is an element comparison function or NULL.
138    HASHCODE_FN is an element hash code function or NULL.
139    DISPOSE_FN is an element disposal function or NULL.
140    ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in
141    the list. The implementation may verify this at runtime.  */
142 /* declared in gl_xlist.h */
143 extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation,
144                                        gl_listelement_equals_fn equals_fn,
145                                        gl_listelement_hashcode_fn hashcode_fn,
146                                        gl_listelement_dispose_fn dispose_fn,
147                                        bool allow_duplicates);
148 /* Likewise.  Return NULL upon out-of-memory.  */
149 extern gl_list_t gl_list_nx_create_empty (gl_list_implementation_t implementation,
150                                           gl_listelement_equals_fn equals_fn,
151                                           gl_listelement_hashcode_fn hashcode_fn,
152                                           gl_listelement_dispose_fn dispose_fn,
153                                           bool allow_duplicates);
154 
155 /* Create a list with given contents.
156    IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST,
157    GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST,
158    GL_RBTREEHASH_LIST.
159    EQUALS_FN is an element comparison function or NULL.
160    HASHCODE_FN is an element hash code function or NULL.
161    DISPOSE_FN is an element disposal function or NULL.
162    ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in
163    the list. The implementation may verify this at runtime.
164    COUNT is the number of initial elements.
165    CONTENTS[0..COUNT-1] is the initial contents.  */
166 /* declared in gl_xlist.h */
167 extern gl_list_t gl_list_create (gl_list_implementation_t implementation,
168                                  gl_listelement_equals_fn equals_fn,
169                                  gl_listelement_hashcode_fn hashcode_fn,
170                                  gl_listelement_dispose_fn dispose_fn,
171                                  bool allow_duplicates,
172                                  size_t count, const void **contents);
173 /* Likewise.  Return NULL upon out-of-memory.  */
174 extern gl_list_t gl_list_nx_create (gl_list_implementation_t implementation,
175                                     gl_listelement_equals_fn equals_fn,
176                                     gl_listelement_hashcode_fn hashcode_fn,
177                                     gl_listelement_dispose_fn dispose_fn,
178                                     bool allow_duplicates,
179                                     size_t count, const void **contents);
180 
181 /* Return the current number of elements in a list.  */
182 extern size_t gl_list_size (gl_list_t list);
183 
184 /* Return the element value represented by a list node.  */
185 extern const void * gl_list_node_value (gl_list_t list, gl_list_node_t node);
186 
187 /* Replace the element value represented by a list node.  */
188 /* declared in gl_xlist.h */
189 extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node,
190                                     const void *elt);
191 /* Likewise.  Return 0 upon success, -1 upon out-of-memory.  */
192 extern int gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node,
193                                       const void *elt)
194 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
195   __attribute__ ((__warn_unused_result__))
196 #endif
197   ;
198 
199 /* Return the node immediately after the given node in the list, or NULL
200    if the given node is the last (rightmost) one in the list.  */
201 extern gl_list_node_t gl_list_next_node (gl_list_t list, gl_list_node_t node);
202 
203 /* Return the node immediately before the given node in the list, or NULL
204    if the given node is the first (leftmost) one in the list.  */
205 extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node);
206 
207 /* Return the element at a given position in the list.
208    POSITION must be >= 0 and < gl_list_size (list).  */
209 extern const void * gl_list_get_at (gl_list_t list, size_t position);
210 
211 /* Replace the element at a given position in the list.
212    POSITION must be >= 0 and < gl_list_size (list).
213    Return its node.  */
214 /* declared in gl_xlist.h */
215 extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position,
216                                       const void *elt);
217 /* Likewise.  Return NULL upon out-of-memory.  */
218 extern gl_list_node_t gl_list_nx_set_at (gl_list_t list, size_t position,
219                                          const void *elt)
220 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
221   __attribute__ ((__warn_unused_result__))
222 #endif
223   ;
224 
225 /* Search whether an element is already in the list.
226    Return its node if found, or NULL if not present in the list.  */
227 extern gl_list_node_t gl_list_search (gl_list_t list, const void *elt);
228 
229 /* Search whether an element is already in the list,
230    at a position >= START_INDEX.
231    Return its node if found, or NULL if not present in the list.  */
232 extern gl_list_node_t gl_list_search_from (gl_list_t list, size_t start_index,
233                                            const void *elt);
234 
235 /* Search whether an element is already in the list,
236    at a position >= START_INDEX and < END_INDEX.
237    Return its node if found, or NULL if not present in the list.  */
238 extern gl_list_node_t gl_list_search_from_to (gl_list_t list,
239                                               size_t start_index,
240                                               size_t end_index,
241                                               const void *elt);
242 
243 /* Search whether an element is already in the list.
244    Return its position if found, or (size_t)(-1) if not present in the list.  */
245 extern size_t gl_list_indexof (gl_list_t list, const void *elt);
246 
247 /* Search whether an element is already in the list,
248    at a position >= START_INDEX.
249    Return its position if found, or (size_t)(-1) if not present in the list.  */
250 extern size_t gl_list_indexof_from (gl_list_t list, size_t start_index,
251                                     const void *elt);
252 
253 /* Search whether an element is already in the list,
254    at a position >= START_INDEX and < END_INDEX.
255    Return its position if found, or (size_t)(-1) if not present in the list.  */
256 extern size_t gl_list_indexof_from_to (gl_list_t list,
257                                        size_t start_index, size_t end_index,
258                                        const void *elt);
259 
260 /* Add an element as the first element of the list.
261    Return its node.  */
262 /* declared in gl_xlist.h */
263 extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt);
264 /* Likewise.  Return NULL upon out-of-memory.  */
265 extern gl_list_node_t gl_list_nx_add_first (gl_list_t list, const void *elt)
266 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
267   __attribute__ ((__warn_unused_result__))
268 #endif
269   ;
270 
271 /* Add an element as the last element of the list.
272    Return its node.  */
273 /* declared in gl_xlist.h */
274 extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt);
275 /* Likewise.  Return NULL upon out-of-memory.  */
276 extern gl_list_node_t gl_list_nx_add_last (gl_list_t list, const void *elt)
277 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
278   __attribute__ ((__warn_unused_result__))
279 #endif
280   ;
281 
282 /* Add an element before a given element node of the list.
283    Return its node.  */
284 /* declared in gl_xlist.h */
285 extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node,
286                                           const void *elt);
287 /* Likewise.  Return NULL upon out-of-memory.  */
288 extern gl_list_node_t gl_list_nx_add_before (gl_list_t list,
289                                              gl_list_node_t node,
290                                              const void *elt)
291 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
292   __attribute__ ((__warn_unused_result__))
293 #endif
294   ;
295 
296 /* Add an element after a given element node of the list.
297    Return its node.  */
298 /* declared in gl_xlist.h */
299 extern gl_list_node_t gl_list_add_after (gl_list_t list, gl_list_node_t node,
300                                          const void *elt);
301 /* Likewise.  Return NULL upon out-of-memory.  */
302 extern gl_list_node_t gl_list_nx_add_after (gl_list_t list, gl_list_node_t node,
303                                             const void *elt)
304 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
305   __attribute__ ((__warn_unused_result__))
306 #endif
307   ;
308 
309 /* Add an element at a given position in the list.
310    POSITION must be >= 0 and <= gl_list_size (list).  */
311 /* declared in gl_xlist.h */
312 extern gl_list_node_t gl_list_add_at (gl_list_t list, size_t position,
313                                       const void *elt);
314 /* Likewise.  Return NULL upon out-of-memory.  */
315 extern gl_list_node_t gl_list_nx_add_at (gl_list_t list, size_t position,
316                                          const void *elt)
317 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
318   __attribute__ ((__warn_unused_result__))
319 #endif
320   ;
321 
322 /* Remove an element from the list.
323    Return true.  */
324 extern bool gl_list_remove_node (gl_list_t list, gl_list_node_t node);
325 
326 /* Remove an element at a given position from the list.
327    POSITION must be >= 0 and < gl_list_size (list).
328    Return true.  */
329 extern bool gl_list_remove_at (gl_list_t list, size_t position);
330 
331 /* Search and remove an element from the list.
332    Return true if it was found and removed.  */
333 extern bool gl_list_remove (gl_list_t list, const void *elt);
334 
335 /* Free an entire list.
336    (But this call does not free the elements of the list.  It only invokes
337    the DISPOSE_FN on each of the elements of the list, and only if the list
338    is not a sublist.)  */
339 extern void gl_list_free (gl_list_t list);
340 
341 #endif /* End of inline and gl_xlist.h-defined functions.  */
342 
343 /* --------------------- gl_list_iterator_t Data Type --------------------- */
344 
345 /* Functions for iterating through a list.  */
346 
347 /* Type of an iterator that traverses a list.
348    This is a fixed-size struct, so that creation of an iterator doesn't need
349    memory allocation on the heap.  */
350 typedef struct
351 {
352   /* For fast dispatch of gl_list_iterator_next.  */
353   const struct gl_list_implementation *vtable;
354   /* For detecting whether the last returned element was removed.  */
355   gl_list_t list;
356   size_t count;
357   /* Other, implementation-private fields.  */
358   void *p; void *q;
359   size_t i; size_t j;
360 } gl_list_iterator_t;
361 
362 #if 0 /* These are defined inline below.  */
363 
364 /* Create an iterator traversing a list.
365    The list contents must not be modified while the iterator is in use,
366    except for replacing or removing the last returned element.  */
367 extern gl_list_iterator_t gl_list_iterator (gl_list_t list);
368 
369 /* Create an iterator traversing the element with indices i,
370    start_index <= i < end_index, of a list.
371    The list contents must not be modified while the iterator is in use,
372    except for replacing or removing the last returned element.  */
373 extern gl_list_iterator_t gl_list_iterator_from_to (gl_list_t list,
374                                                     size_t start_index,
375                                                     size_t end_index);
376 
377 /* If there is a next element, store the next element in *ELTP, store its
378    node in *NODEP if NODEP is non-NULL, advance the iterator and return true.
379    Otherwise, return false.  */
380 extern bool gl_list_iterator_next (gl_list_iterator_t *iterator,
381                                    const void **eltp, gl_list_node_t *nodep);
382 
383 /* Free an iterator.  */
384 extern void gl_list_iterator_free (gl_list_iterator_t *iterator);
385 
386 #endif /* End of inline functions.  */
387 
388 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
389 
390 /* The following functions are for lists without duplicates where the
391    order is given by a sort criterion.  */
392 
393 /* Type of function used to compare two elements.  Same as for qsort().
394    NULL denotes pointer comparison.  */
395 typedef int (*gl_listelement_compar_fn) (const void *elt1, const void *elt2);
396 
397 #if 0 /* Unless otherwise specified, these are defined inline below.  */
398 
399 /* Search whether an element is already in the list.
400    The list is assumed to be sorted with COMPAR.
401    Return its node if found, or NULL if not present in the list.
402    If the list contains several copies of ELT, the node of the leftmost one is
403    returned.  */
404 extern gl_list_node_t gl_sortedlist_search (gl_list_t list,
405                                             gl_listelement_compar_fn compar,
406                                             const void *elt);
407 
408 /* Search whether an element is already in the list.
409    The list is assumed to be sorted with COMPAR.
410    Only list elements with indices >= START_INDEX and < END_INDEX are
411    considered; the implementation uses these bounds to minimize the number
412    of COMPAR invocations.
413    Return its node if found, or NULL if not present in the list.
414    If the list contains several copies of ELT, the node of the leftmost one is
415    returned.  */
416 extern gl_list_node_t gl_sortedlist_search_from_to (gl_list_t list,
417                                                     gl_listelement_compar_fn compar,
418                                                     size_t start_index,
419                                                     size_t end_index,
420                                                     const void *elt);
421 
422 /* Search whether an element is already in the list.
423    The list is assumed to be sorted with COMPAR.
424    Return its position if found, or (size_t)(-1) if not present in the list.
425    If the list contains several copies of ELT, the position of the leftmost one
426    is returned.  */
427 extern size_t gl_sortedlist_indexof (gl_list_t list,
428                                      gl_listelement_compar_fn compar,
429                                      const void *elt);
430 
431 /* Search whether an element is already in the list.
432    The list is assumed to be sorted with COMPAR.
433    Only list elements with indices >= START_INDEX and < END_INDEX are
434    considered; the implementation uses these bounds to minimize the number
435    of COMPAR invocations.
436    Return its position if found, or (size_t)(-1) if not present in the list.
437    If the list contains several copies of ELT, the position of the leftmost one
438    is returned.  */
439 extern size_t gl_sortedlist_indexof_from_to (gl_list_t list,
440                                              gl_listelement_compar_fn compar,
441                                              size_t start_index,
442                                              size_t end_index,
443                                              const void *elt);
444 
445 /* Add an element at the appropriate position in the list.
446    The list is assumed to be sorted with COMPAR.
447    Return its node.  */
448 /* declared in gl_xlist.h */
449 extern gl_list_node_t gl_sortedlist_add (gl_list_t list,
450                                          gl_listelement_compar_fn compar,
451                                          const void *elt);
452 /* Likewise.  Return NULL upon out-of-memory.  */
453 extern gl_list_node_t gl_sortedlist_nx_add (gl_list_t list,
454                                             gl_listelement_compar_fn compar,
455                                             const void *elt)
456 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
457   __attribute__ ((__warn_unused_result__))
458 #endif
459   ;
460 
461 /* Search and remove an element from the list.
462    The list is assumed to be sorted with COMPAR.
463    Return true if it was found and removed.
464    If the list contains several copies of ELT, only the leftmost one is
465    removed.  */
466 extern bool gl_sortedlist_remove (gl_list_t list,
467                                   gl_listelement_compar_fn compar,
468                                   const void *elt);
469 
470 #endif /* End of inline and gl_xlist.h-defined functions.  */
471 
472 /* ------------------------ Implementation Details ------------------------ */
473 
474 struct gl_list_implementation
475 {
476   /* gl_list_t functions.  */
477   gl_list_t (*nx_create_empty) (gl_list_implementation_t implementation,
478                                 gl_listelement_equals_fn equals_fn,
479                                 gl_listelement_hashcode_fn hashcode_fn,
480                                 gl_listelement_dispose_fn dispose_fn,
481                                 bool allow_duplicates);
482   gl_list_t (*nx_create) (gl_list_implementation_t implementation,
483                           gl_listelement_equals_fn equals_fn,
484                           gl_listelement_hashcode_fn hashcode_fn,
485                           gl_listelement_dispose_fn dispose_fn,
486                           bool allow_duplicates,
487                           size_t count, const void **contents);
488   size_t (*size) (gl_list_t list);
489   const void * (*node_value) (gl_list_t list, gl_list_node_t node);
490   int (*node_nx_set_value) (gl_list_t list, gl_list_node_t node,
491                             const void *elt);
492   gl_list_node_t (*next_node) (gl_list_t list, gl_list_node_t node);
493   gl_list_node_t (*previous_node) (gl_list_t list, gl_list_node_t node);
494   const void * (*get_at) (gl_list_t list, size_t position);
495   gl_list_node_t (*nx_set_at) (gl_list_t list, size_t position,
496                                const void *elt);
497   gl_list_node_t (*search_from_to) (gl_list_t list, size_t start_index,
498                                     size_t end_index, const void *elt);
499   size_t (*indexof_from_to) (gl_list_t list, size_t start_index,
500                              size_t end_index, const void *elt);
501   gl_list_node_t (*nx_add_first) (gl_list_t list, const void *elt);
502   gl_list_node_t (*nx_add_last) (gl_list_t list, const void *elt);
503   gl_list_node_t (*nx_add_before) (gl_list_t list, gl_list_node_t node,
504                                    const void *elt);
505   gl_list_node_t (*nx_add_after) (gl_list_t list, gl_list_node_t node,
506                                   const void *elt);
507   gl_list_node_t (*nx_add_at) (gl_list_t list, size_t position,
508                                const void *elt);
509   bool (*remove_node) (gl_list_t list, gl_list_node_t node);
510   bool (*remove_at) (gl_list_t list, size_t position);
511   bool (*remove_elt) (gl_list_t list, const void *elt);
512   void (*list_free) (gl_list_t list);
513   /* gl_list_iterator_t functions.  */
514   gl_list_iterator_t (*iterator) (gl_list_t list);
515   gl_list_iterator_t (*iterator_from_to) (gl_list_t list,
516                                           size_t start_index,
517                                           size_t end_index);
518   bool (*iterator_next) (gl_list_iterator_t *iterator,
519                          const void **eltp, gl_list_node_t *nodep);
520   void (*iterator_free) (gl_list_iterator_t *iterator);
521   /* Sorted gl_list_t functions.  */
522   gl_list_node_t (*sortedlist_search) (gl_list_t list,
523                                        gl_listelement_compar_fn compar,
524                                        const void *elt);
525   gl_list_node_t (*sortedlist_search_from_to) (gl_list_t list,
526                                                gl_listelement_compar_fn compar,
527                                                size_t start_index,
528                                                size_t end_index,
529                                                const void *elt);
530   size_t (*sortedlist_indexof) (gl_list_t list,
531                                 gl_listelement_compar_fn compar,
532                                 const void *elt);
533   size_t (*sortedlist_indexof_from_to) (gl_list_t list,
534                                         gl_listelement_compar_fn compar,
535                                         size_t start_index, size_t end_index,
536                                         const void *elt);
537   gl_list_node_t (*sortedlist_nx_add) (gl_list_t list,
538                                        gl_listelement_compar_fn compar,
539                                     const void *elt);
540   bool (*sortedlist_remove) (gl_list_t list,
541                              gl_listelement_compar_fn compar,
542                              const void *elt);
543 };
544 
545 struct gl_list_impl_base
546 {
547   const struct gl_list_implementation *vtable;
548   gl_listelement_equals_fn equals_fn;
549   gl_listelement_hashcode_fn hashcode_fn;
550   gl_listelement_dispose_fn dispose_fn;
551   bool allow_duplicates;
552 };
553 
554 /* Define all functions of this file as accesses to the
555    struct gl_list_implementation.  */
556 
557 GL_LIST_INLINE gl_list_t
gl_list_nx_create_empty(gl_list_implementation_t implementation,gl_listelement_equals_fn equals_fn,gl_listelement_hashcode_fn hashcode_fn,gl_listelement_dispose_fn dispose_fn,bool allow_duplicates)558 gl_list_nx_create_empty (gl_list_implementation_t implementation,
559                          gl_listelement_equals_fn equals_fn,
560                          gl_listelement_hashcode_fn hashcode_fn,
561                          gl_listelement_dispose_fn dispose_fn,
562                          bool allow_duplicates)
563 {
564   return implementation->nx_create_empty (implementation, equals_fn,
565                                           hashcode_fn, dispose_fn,
566                                           allow_duplicates);
567 }
568 
569 GL_LIST_INLINE gl_list_t
gl_list_nx_create(gl_list_implementation_t implementation,gl_listelement_equals_fn equals_fn,gl_listelement_hashcode_fn hashcode_fn,gl_listelement_dispose_fn dispose_fn,bool allow_duplicates,size_t count,const void ** contents)570 gl_list_nx_create (gl_list_implementation_t implementation,
571                    gl_listelement_equals_fn equals_fn,
572                    gl_listelement_hashcode_fn hashcode_fn,
573                    gl_listelement_dispose_fn dispose_fn,
574                    bool allow_duplicates,
575                    size_t count, const void **contents)
576 {
577   return implementation->nx_create (implementation, equals_fn, hashcode_fn,
578                                     dispose_fn, allow_duplicates, count,
579                                     contents);
580 }
581 
582 GL_LIST_INLINE size_t
gl_list_size(gl_list_t list)583 gl_list_size (gl_list_t list)
584 {
585   return ((const struct gl_list_impl_base *) list)->vtable
586          ->size (list);
587 }
588 
589 GL_LIST_INLINE const void *
gl_list_node_value(gl_list_t list,gl_list_node_t node)590 gl_list_node_value (gl_list_t list, gl_list_node_t node)
591 {
592   return ((const struct gl_list_impl_base *) list)->vtable
593          ->node_value (list, node);
594 }
595 
596 GL_LIST_INLINE int
597 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
598   __attribute__ ((__warn_unused_result__))
599 #endif
gl_list_node_nx_set_value(gl_list_t list,gl_list_node_t node,const void * elt)600 gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node,
601                            const void *elt)
602 {
603   return ((const struct gl_list_impl_base *) list)->vtable
604          ->node_nx_set_value (list, node, elt);
605 }
606 
607 GL_LIST_INLINE gl_list_node_t
gl_list_next_node(gl_list_t list,gl_list_node_t node)608 gl_list_next_node (gl_list_t list, gl_list_node_t node)
609 {
610   return ((const struct gl_list_impl_base *) list)->vtable
611          ->next_node (list, node);
612 }
613 
614 GL_LIST_INLINE gl_list_node_t
gl_list_previous_node(gl_list_t list,gl_list_node_t node)615 gl_list_previous_node (gl_list_t list, gl_list_node_t node)
616 {
617   return ((const struct gl_list_impl_base *) list)->vtable
618          ->previous_node (list, node);
619 }
620 
621 GL_LIST_INLINE const void *
gl_list_get_at(gl_list_t list,size_t position)622 gl_list_get_at (gl_list_t list, size_t position)
623 {
624   return ((const struct gl_list_impl_base *) list)->vtable
625          ->get_at (list, position);
626 }
627 
628 GL_LIST_INLINE gl_list_node_t
629 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
630   __attribute__ ((__warn_unused_result__))
631 #endif
gl_list_nx_set_at(gl_list_t list,size_t position,const void * elt)632 gl_list_nx_set_at (gl_list_t list, size_t position, const void *elt)
633 {
634   return ((const struct gl_list_impl_base *) list)->vtable
635          ->nx_set_at (list, position, elt);
636 }
637 
638 GL_LIST_INLINE gl_list_node_t
gl_list_search(gl_list_t list,const void * elt)639 gl_list_search (gl_list_t list, const void *elt)
640 {
641   size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
642   return ((const struct gl_list_impl_base *) list)->vtable
643          ->search_from_to (list, 0, size, elt);
644 }
645 
646 GL_LIST_INLINE gl_list_node_t
gl_list_search_from(gl_list_t list,size_t start_index,const void * elt)647 gl_list_search_from (gl_list_t list, size_t start_index, const void *elt)
648 {
649   size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
650   return ((const struct gl_list_impl_base *) list)->vtable
651          ->search_from_to (list, start_index, size, elt);
652 }
653 
654 GL_LIST_INLINE gl_list_node_t
gl_list_search_from_to(gl_list_t list,size_t start_index,size_t end_index,const void * elt)655 gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
656                         const void *elt)
657 {
658   return ((const struct gl_list_impl_base *) list)->vtable
659          ->search_from_to (list, start_index, end_index, elt);
660 }
661 
662 GL_LIST_INLINE size_t
gl_list_indexof(gl_list_t list,const void * elt)663 gl_list_indexof (gl_list_t list, const void *elt)
664 {
665   size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
666   return ((const struct gl_list_impl_base *) list)->vtable
667          ->indexof_from_to (list, 0, size, elt);
668 }
669 
670 GL_LIST_INLINE size_t
gl_list_indexof_from(gl_list_t list,size_t start_index,const void * elt)671 gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt)
672 {
673   size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
674   return ((const struct gl_list_impl_base *) list)->vtable
675          ->indexof_from_to (list, start_index, size, elt);
676 }
677 
678 GL_LIST_INLINE size_t
gl_list_indexof_from_to(gl_list_t list,size_t start_index,size_t end_index,const void * elt)679 gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
680                          const void *elt)
681 {
682   return ((const struct gl_list_impl_base *) list)->vtable
683          ->indexof_from_to (list, start_index, end_index, elt);
684 }
685 
686 GL_LIST_INLINE gl_list_node_t
687 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
688   __attribute__ ((__warn_unused_result__))
689 #endif
gl_list_nx_add_first(gl_list_t list,const void * elt)690 gl_list_nx_add_first (gl_list_t list, const void *elt)
691 {
692   return ((const struct gl_list_impl_base *) list)->vtable
693          ->nx_add_first (list, elt);
694 }
695 
696 GL_LIST_INLINE gl_list_node_t
697 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
698   __attribute__ ((__warn_unused_result__))
699 #endif
gl_list_nx_add_last(gl_list_t list,const void * elt)700 gl_list_nx_add_last (gl_list_t list, const void *elt)
701 {
702   return ((const struct gl_list_impl_base *) list)->vtable
703          ->nx_add_last (list, elt);
704 }
705 
706 GL_LIST_INLINE gl_list_node_t
707 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
708   __attribute__ ((__warn_unused_result__))
709 #endif
gl_list_nx_add_before(gl_list_t list,gl_list_node_t node,const void * elt)710 gl_list_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
711 {
712   return ((const struct gl_list_impl_base *) list)->vtable
713          ->nx_add_before (list, node, elt);
714 }
715 
716 GL_LIST_INLINE gl_list_node_t
717 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
718   __attribute__ ((__warn_unused_result__))
719 #endif
gl_list_nx_add_after(gl_list_t list,gl_list_node_t node,const void * elt)720 gl_list_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
721 {
722   return ((const struct gl_list_impl_base *) list)->vtable
723          ->nx_add_after (list, node, elt);
724 }
725 
726 GL_LIST_INLINE gl_list_node_t
727 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
728   __attribute__ ((__warn_unused_result__))
729 #endif
gl_list_nx_add_at(gl_list_t list,size_t position,const void * elt)730 gl_list_nx_add_at (gl_list_t list, size_t position, const void *elt)
731 {
732   return ((const struct gl_list_impl_base *) list)->vtable
733          ->nx_add_at (list, position, elt);
734 }
735 
736 GL_LIST_INLINE bool
gl_list_remove_node(gl_list_t list,gl_list_node_t node)737 gl_list_remove_node (gl_list_t list, gl_list_node_t node)
738 {
739   return ((const struct gl_list_impl_base *) list)->vtable
740          ->remove_node (list, node);
741 }
742 
743 GL_LIST_INLINE bool
gl_list_remove_at(gl_list_t list,size_t position)744 gl_list_remove_at (gl_list_t list, size_t position)
745 {
746   return ((const struct gl_list_impl_base *) list)->vtable
747          ->remove_at (list, position);
748 }
749 
750 GL_LIST_INLINE bool
gl_list_remove(gl_list_t list,const void * elt)751 gl_list_remove (gl_list_t list, const void *elt)
752 {
753   return ((const struct gl_list_impl_base *) list)->vtable
754          ->remove_elt (list, elt);
755 }
756 
757 GL_LIST_INLINE void
gl_list_free(gl_list_t list)758 gl_list_free (gl_list_t list)
759 {
760   ((const struct gl_list_impl_base *) list)->vtable->list_free (list);
761 }
762 
763 GL_LIST_INLINE gl_list_iterator_t
gl_list_iterator(gl_list_t list)764 gl_list_iterator (gl_list_t list)
765 {
766   return ((const struct gl_list_impl_base *) list)->vtable
767          ->iterator (list);
768 }
769 
770 GL_LIST_INLINE gl_list_iterator_t
gl_list_iterator_from_to(gl_list_t list,size_t start_index,size_t end_index)771 gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
772 {
773   return ((const struct gl_list_impl_base *) list)->vtable
774          ->iterator_from_to (list, start_index, end_index);
775 }
776 
777 GL_LIST_INLINE bool
gl_list_iterator_next(gl_list_iterator_t * iterator,const void ** eltp,gl_list_node_t * nodep)778 gl_list_iterator_next (gl_list_iterator_t *iterator,
779                        const void **eltp, gl_list_node_t *nodep)
780 {
781   return iterator->vtable->iterator_next (iterator, eltp, nodep);
782 }
783 
784 GL_LIST_INLINE void
gl_list_iterator_free(gl_list_iterator_t * iterator)785 gl_list_iterator_free (gl_list_iterator_t *iterator)
786 {
787   iterator->vtable->iterator_free (iterator);
788 }
789 
790 GL_LIST_INLINE gl_list_node_t
gl_sortedlist_search(gl_list_t list,gl_listelement_compar_fn compar,const void * elt)791 gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
792 {
793   return ((const struct gl_list_impl_base *) list)->vtable
794          ->sortedlist_search (list, compar, elt);
795 }
796 
797 GL_LIST_INLINE gl_list_node_t
gl_sortedlist_search_from_to(gl_list_t list,gl_listelement_compar_fn compar,size_t start_index,size_t end_index,const void * elt)798 gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
799 {
800   return ((const struct gl_list_impl_base *) list)->vtable
801          ->sortedlist_search_from_to (list, compar, start_index, end_index,
802                                       elt);
803 }
804 
805 GL_LIST_INLINE size_t
gl_sortedlist_indexof(gl_list_t list,gl_listelement_compar_fn compar,const void * elt)806 gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
807 {
808   return ((const struct gl_list_impl_base *) list)->vtable
809          ->sortedlist_indexof (list, compar, elt);
810 }
811 
812 GL_LIST_INLINE size_t
gl_sortedlist_indexof_from_to(gl_list_t list,gl_listelement_compar_fn compar,size_t start_index,size_t end_index,const void * elt)813 gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
814 {
815   return ((const struct gl_list_impl_base *) list)->vtable
816          ->sortedlist_indexof_from_to (list, compar, start_index, end_index,
817                                        elt);
818 }
819 
820 GL_LIST_INLINE gl_list_node_t
821 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
822   __attribute__ ((__warn_unused_result__))
823 #endif
gl_sortedlist_nx_add(gl_list_t list,gl_listelement_compar_fn compar,const void * elt)824 gl_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
825 {
826   return ((const struct gl_list_impl_base *) list)->vtable
827          ->sortedlist_nx_add (list, compar, elt);
828 }
829 
830 GL_LIST_INLINE bool
gl_sortedlist_remove(gl_list_t list,gl_listelement_compar_fn compar,const void * elt)831 gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
832 {
833   return ((const struct gl_list_impl_base *) list)->vtable
834          ->sortedlist_remove (list, compar, elt);
835 }
836 
837 #ifdef __cplusplus
838 }
839 #endif
840 
841 _GL_INLINE_HEADER_END
842 
843 #endif /* _GL_LIST_H */
844