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