Coverage Report

Created: 2024-06-20 06:28

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