1 /* Sequential list data type implemented by a linked list.
2 Copyright (C) 2006-2019 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Common code of gl_linked_list.c and gl_linkedhash_list.c. */
20 /* If the symbol SIGNAL_SAFE_LIST is defined, the code is compiled in such
21 a way that a gl_list_t data structure may be used from within a signal
22 handler. The operations allowed in the signal handler are:
23 gl_list_iterator, gl_list_iterator_next, gl_list_iterator_free.
24 The list and node fields that are therefore accessed from the signal handler
26 list->root, node->next, node->value.
27 We are careful to make modifications to these fields only in an order
28 that maintains the consistency of the list data structure at any moment,
29 and we use 'volatile' assignments to prevent the compiler from reordering
31 #ifdef SIGNAL_SAFE_LIST
32 # define ASYNCSAFE(type) *(type volatile *)&
34 # define ASYNCSAFE(type)
37 /* -------------------------- gl_list_t Data Type -------------------------- */
40 gl_linked_nx_create_empty (gl_list_implementation_t implementation
,
41 gl_listelement_equals_fn equals_fn
,
42 gl_listelement_hashcode_fn hashcode_fn
,
43 gl_listelement_dispose_fn dispose_fn
,
44 bool allow_duplicates
)
46 struct gl_list_impl
*list
=
47 (struct gl_list_impl
*) malloc (sizeof (struct gl_list_impl
));
52 list
->base
.vtable
= implementation
;
53 list
->base
.equals_fn
= equals_fn
;
54 list
->base
.hashcode_fn
= hashcode_fn
;
55 list
->base
.dispose_fn
= dispose_fn
;
56 list
->base
.allow_duplicates
= allow_duplicates
;
58 list
->table_size
= 11;
60 (gl_hash_entry_t
*) calloc (list
->table_size
, sizeof (gl_hash_entry_t
));
61 if (list
->table
== NULL
)
64 list
->root
.next
= &list
->root
;
65 list
->root
.prev
= &list
->root
;
78 gl_linked_nx_create (gl_list_implementation_t implementation
,
79 gl_listelement_equals_fn equals_fn
,
80 gl_listelement_hashcode_fn hashcode_fn
,
81 gl_listelement_dispose_fn dispose_fn
,
82 bool allow_duplicates
,
83 size_t count
, const void **contents
)
85 struct gl_list_impl
*list
=
86 (struct gl_list_impl
*) malloc (sizeof (struct gl_list_impl
));
92 list
->base
.vtable
= implementation
;
93 list
->base
.equals_fn
= equals_fn
;
94 list
->base
.hashcode_fn
= hashcode_fn
;
95 list
->base
.dispose_fn
= dispose_fn
;
96 list
->base
.allow_duplicates
= allow_duplicates
;
99 size_t estimate
= xsum (count
, count
/ 2); /* 1.5 * count */
102 list
->table_size
= next_prime (estimate
);
103 if (size_overflow_p (xtimes (list
->table_size
, sizeof (gl_hash_entry_t
))))
106 (gl_hash_entry_t
*) calloc (list
->table_size
, sizeof (gl_hash_entry_t
));
107 if (list
->table
== NULL
)
113 for (; count
> 0; contents
++, count
--)
115 gl_list_node_t node
=
116 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
121 node
->value
= *contents
;
124 (list
->base
.hashcode_fn
!= NULL
125 ? list
->base
.hashcode_fn (node
->value
)
126 : (size_t)(uintptr_t) node
->value
);
128 /* Add node to the hash table. */
129 if (add_to_bucket (list
, node
) < 0)
136 /* Add node to the list. */
141 tail
->next
= &list
->root
;
142 list
->root
.prev
= tail
;
150 for (node
= tail
; node
!= &list
->root
; )
152 gl_list_node_t prev
= node
->prev
;
166 static size_t _GL_ATTRIBUTE_PURE
167 gl_linked_size (gl_list_t list
)
172 static const void * _GL_ATTRIBUTE_PURE
173 gl_linked_node_value (gl_list_t list
, gl_list_node_t node
)
179 gl_linked_node_nx_set_value (gl_list_t list
, gl_list_node_t node
,
183 if (elt
!= node
->value
)
185 size_t new_hashcode
=
186 (list
->base
.hashcode_fn
!= NULL
187 ? list
->base
.hashcode_fn (elt
)
188 : (size_t)(uintptr_t) elt
);
190 if (new_hashcode
!= node
->h
.hashcode
)
192 remove_from_bucket (list
, node
);
194 node
->h
.hashcode
= new_hashcode
;
195 if (add_to_bucket (list
, node
) < 0)
197 /* Out of memory. We removed node from a bucket but cannot add
198 it to another bucket. In order to avoid inconsistencies, we
199 must remove node entirely from the list. */
200 gl_list_node_t before_removed
= node
->prev
;
201 gl_list_node_t after_removed
= node
->next
;
202 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= after_removed
;
203 after_removed
->prev
= before_removed
;
218 static gl_list_node_t _GL_ATTRIBUTE_PURE
219 gl_linked_next_node (gl_list_t list
, gl_list_node_t node
)
221 return (node
->next
!= &list
->root
? node
->next
: NULL
);
224 static gl_list_node_t _GL_ATTRIBUTE_PURE
225 gl_linked_previous_node (gl_list_t list
, gl_list_node_t node
)
227 return (node
->prev
!= &list
->root
? node
->prev
: NULL
);
230 static const void * _GL_ATTRIBUTE_PURE
231 gl_linked_get_at (gl_list_t list
, size_t position
)
233 size_t count
= list
->count
;
236 if (!(position
< count
))
237 /* Invalid argument. */
239 /* Here we know count > 0. */
240 if (position
<= ((count
- 1) / 2))
242 node
= list
->root
.next
;
243 for (; position
> 0; position
--)
248 position
= count
- 1 - position
;
249 node
= list
->root
.prev
;
250 for (; position
> 0; position
--)
256 static gl_list_node_t
257 gl_linked_nx_set_at (gl_list_t list
, size_t position
, const void *elt
)
259 size_t count
= list
->count
;
262 if (!(position
< count
))
263 /* Invalid argument. */
265 /* Here we know count > 0. */
266 if (position
<= ((count
- 1) / 2))
268 node
= list
->root
.next
;
269 for (; position
> 0; position
--)
274 position
= count
- 1 - position
;
275 node
= list
->root
.prev
;
276 for (; position
> 0; position
--)
280 if (elt
!= node
->value
)
282 size_t new_hashcode
=
283 (list
->base
.hashcode_fn
!= NULL
284 ? list
->base
.hashcode_fn (elt
)
285 : (size_t)(uintptr_t) elt
);
287 if (new_hashcode
!= node
->h
.hashcode
)
289 remove_from_bucket (list
, node
);
291 node
->h
.hashcode
= new_hashcode
;
292 if (add_to_bucket (list
, node
) < 0)
294 /* Out of memory. We removed node from a bucket but cannot add
295 it to another bucket. In order to avoid inconsistencies, we
296 must remove node entirely from the list. */
297 gl_list_node_t before_removed
= node
->prev
;
298 gl_list_node_t after_removed
= node
->next
;
299 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= after_removed
;
300 after_removed
->prev
= before_removed
;
315 static gl_list_node_t _GL_ATTRIBUTE_PURE
316 gl_linked_search_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
319 size_t count
= list
->count
;
321 if (!(start_index
<= end_index
&& end_index
<= count
))
322 /* Invalid arguments. */
327 (list
->base
.hashcode_fn
!= NULL
328 ? list
->base
.hashcode_fn (elt
)
329 : (size_t)(uintptr_t) elt
);
330 size_t bucket
= hashcode
% list
->table_size
;
331 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
333 if (!list
->base
.allow_duplicates
)
335 /* Look for the first match in the hash bucket. */
336 gl_list_node_t found
= NULL
;
339 for (node
= (gl_list_node_t
) list
->table
[bucket
];
341 node
= (gl_list_node_t
) node
->h
.hash_next
)
342 if (node
->h
.hashcode
== hashcode
344 ? equals (elt
, node
->value
)
345 : elt
== node
->value
))
351 /* Look whether found's index is < start_index. */
352 for (node
= list
->root
.next
; ; node
= node
->next
)
356 if (--start_index
== 0)
359 if (end_index
< count
)
360 /* Look whether found's index is >= end_index. */
362 end_index
= count
- end_index
;
363 for (node
= list
->root
.prev
; ; node
= node
->prev
)
367 if (--end_index
== 0)
375 /* Look whether there is more than one match in the hash bucket. */
376 bool multiple_matches
= false;
377 gl_list_node_t first_match
= NULL
;
380 for (node
= (gl_list_node_t
) list
->table
[bucket
];
382 node
= (gl_list_node_t
) node
->h
.hash_next
)
383 if (node
->h
.hashcode
== hashcode
385 ? equals (elt
, node
->value
)
386 : elt
== node
->value
))
388 if (first_match
== NULL
)
392 multiple_matches
= true;
396 if (multiple_matches
)
398 /* We need the match with the smallest index. But we don't have
399 a fast mapping node -> index. So we have to walk the list. */
400 end_index
-= start_index
;
401 node
= list
->root
.next
;
402 for (; start_index
> 0; start_index
--)
407 node
= node
->next
, end_index
--)
408 if (node
->h
.hashcode
== hashcode
410 ? equals (elt
, node
->value
)
411 : elt
== node
->value
))
413 /* The matches must have all been at indices < start_index or
420 /* Look whether first_match's index is < start_index. */
421 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
423 if (node
== first_match
)
425 if (--start_index
== 0)
428 if (end_index
< list
->count
)
429 /* Look whether first_match's index is >= end_index. */
431 end_index
= list
->count
- end_index
;
432 for (node
= list
->root
.prev
; ; node
= node
->prev
)
434 if (node
== first_match
)
436 if (--end_index
== 0)
444 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
445 gl_list_node_t node
= list
->root
.next
;
447 end_index
-= start_index
;
448 for (; start_index
> 0; start_index
--)
453 for (; end_index
> 0; node
= node
->next
, end_index
--)
454 if (equals (elt
, node
->value
))
459 for (; end_index
> 0; node
= node
->next
, end_index
--)
460 if (elt
== node
->value
)
468 static size_t _GL_ATTRIBUTE_PURE
469 gl_linked_indexof_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
472 size_t count
= list
->count
;
474 if (!(start_index
<= end_index
&& end_index
<= count
))
475 /* Invalid arguments. */
479 /* Here the hash table doesn't help much. It only allows us to minimize
480 the number of equals() calls, by looking up first the node and then
483 (list
->base
.hashcode_fn
!= NULL
484 ? list
->base
.hashcode_fn (elt
)
485 : (size_t)(uintptr_t) elt
);
486 size_t bucket
= hashcode
% list
->table_size
;
487 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
490 /* First step: Look up the node. */
491 if (!list
->base
.allow_duplicates
)
493 /* Look for the first match in the hash bucket. */
494 for (node
= (gl_list_node_t
) list
->table
[bucket
];
496 node
= (gl_list_node_t
) node
->h
.hash_next
)
497 if (node
->h
.hashcode
== hashcode
499 ? equals (elt
, node
->value
)
500 : elt
== node
->value
))
505 /* Look whether there is more than one match in the hash bucket. */
506 bool multiple_matches
= false;
507 gl_list_node_t first_match
= NULL
;
509 for (node
= (gl_list_node_t
) list
->table
[bucket
];
511 node
= (gl_list_node_t
) node
->h
.hash_next
)
512 if (node
->h
.hashcode
== hashcode
514 ? equals (elt
, node
->value
)
515 : elt
== node
->value
))
517 if (first_match
== NULL
)
521 multiple_matches
= true;
525 if (multiple_matches
)
527 /* We need the match with the smallest index. But we don't have
528 a fast mapping node -> index. So we have to walk the list. */
532 node
= list
->root
.next
;
533 for (; start_index
> 0; start_index
--)
538 node
= node
->next
, index
++)
539 if (node
->h
.hashcode
== hashcode
541 ? equals (elt
, node
->value
)
542 : elt
== node
->value
))
544 /* The matches must have all been at indices < start_index or
551 /* Second step: Look up the index of the node. */
558 for (; node
->prev
!= &list
->root
; node
= node
->prev
)
561 if (index
>= start_index
&& index
< end_index
)
567 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
568 size_t index
= start_index
;
569 gl_list_node_t node
= list
->root
.next
;
571 for (; start_index
> 0; start_index
--)
578 node
= node
->next
, index
++)
579 if (equals (elt
, node
->value
))
586 node
= node
->next
, index
++)
587 if (elt
== node
->value
)
595 static gl_list_node_t
596 gl_linked_nx_add_first (gl_list_t list
, const void *elt
)
598 gl_list_node_t node
=
599 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
604 ASYNCSAFE(const void *) node
->value
= elt
;
607 (list
->base
.hashcode_fn
!= NULL
608 ? list
->base
.hashcode_fn (node
->value
)
609 : (size_t)(uintptr_t) node
->value
);
611 /* Add node to the hash table. */
612 if (add_to_bucket (list
, node
) < 0)
619 /* Add node to the list. */
620 node
->prev
= &list
->root
;
621 ASYNCSAFE(gl_list_node_t
) node
->next
= list
->root
.next
;
622 node
->next
->prev
= node
;
623 ASYNCSAFE(gl_list_node_t
) list
->root
.next
= node
;
627 hash_resize_after_add (list
);
633 static gl_list_node_t
634 gl_linked_nx_add_last (gl_list_t list
, const void *elt
)
636 gl_list_node_t node
=
637 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
642 ASYNCSAFE(const void *) node
->value
= elt
;
645 (list
->base
.hashcode_fn
!= NULL
646 ? list
->base
.hashcode_fn (node
->value
)
647 : (size_t)(uintptr_t) node
->value
);
649 /* Add node to the hash table. */
650 if (add_to_bucket (list
, node
) < 0)
657 /* Add node to the list. */
658 ASYNCSAFE(gl_list_node_t
) node
->next
= &list
->root
;
659 node
->prev
= list
->root
.prev
;
660 ASYNCSAFE(gl_list_node_t
) node
->prev
->next
= node
;
661 list
->root
.prev
= node
;
665 hash_resize_after_add (list
);
671 static gl_list_node_t
672 gl_linked_nx_add_before (gl_list_t list
, gl_list_node_t node
, const void *elt
)
674 gl_list_node_t new_node
=
675 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
677 if (new_node
== NULL
)
680 ASYNCSAFE(const void *) new_node
->value
= elt
;
682 new_node
->h
.hashcode
=
683 (list
->base
.hashcode_fn
!= NULL
684 ? list
->base
.hashcode_fn (new_node
->value
)
685 : (size_t)(uintptr_t) new_node
->value
);
687 /* Add new_node to the hash table. */
688 if (add_to_bucket (list
, new_node
) < 0)
695 /* Add new_node to the list. */
696 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
;
697 new_node
->prev
= node
->prev
;
698 ASYNCSAFE(gl_list_node_t
) new_node
->prev
->next
= new_node
;
699 node
->prev
= new_node
;
703 hash_resize_after_add (list
);
709 static gl_list_node_t
710 gl_linked_nx_add_after (gl_list_t list
, gl_list_node_t node
, const void *elt
)
712 gl_list_node_t new_node
=
713 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
715 if (new_node
== NULL
)
718 ASYNCSAFE(const void *) new_node
->value
= elt
;
720 new_node
->h
.hashcode
=
721 (list
->base
.hashcode_fn
!= NULL
722 ? list
->base
.hashcode_fn (new_node
->value
)
723 : (size_t)(uintptr_t) new_node
->value
);
725 /* Add new_node to the hash table. */
726 if (add_to_bucket (list
, new_node
) < 0)
733 /* Add new_node to the list. */
734 new_node
->prev
= node
;
735 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
->next
;
736 new_node
->next
->prev
= new_node
;
737 ASYNCSAFE(gl_list_node_t
) node
->next
= new_node
;
741 hash_resize_after_add (list
);
747 static gl_list_node_t
748 gl_linked_nx_add_at (gl_list_t list
, size_t position
, const void *elt
)
750 size_t count
= list
->count
;
751 gl_list_node_t new_node
;
753 if (!(position
<= count
))
754 /* Invalid argument. */
757 new_node
= (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
758 if (new_node
== NULL
)
761 ASYNCSAFE(const void *) new_node
->value
= elt
;
763 new_node
->h
.hashcode
=
764 (list
->base
.hashcode_fn
!= NULL
765 ? list
->base
.hashcode_fn (new_node
->value
)
766 : (size_t)(uintptr_t) new_node
->value
);
768 /* Add new_node to the hash table. */
769 if (add_to_bucket (list
, new_node
) < 0)
776 /* Add new_node to the list. */
777 if (position
<= (count
/ 2))
782 for (; position
> 0; position
--)
784 new_node
->prev
= node
;
785 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
->next
;
786 new_node
->next
->prev
= new_node
;
787 ASYNCSAFE(gl_list_node_t
) node
->next
= new_node
;
793 position
= count
- position
;
795 for (; position
> 0; position
--)
797 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
;
798 new_node
->prev
= node
->prev
;
799 ASYNCSAFE(gl_list_node_t
) new_node
->prev
->next
= new_node
;
800 node
->prev
= new_node
;
805 hash_resize_after_add (list
);
812 gl_linked_remove_node (gl_list_t list
, gl_list_node_t node
)
818 /* Remove node from the hash table. */
819 remove_from_bucket (list
, node
);
822 /* Remove node from the list. */
826 ASYNCSAFE(gl_list_node_t
) prev
->next
= next
;
830 if (list
->base
.dispose_fn
!= NULL
)
831 list
->base
.dispose_fn (node
->value
);
837 gl_linked_remove_at (gl_list_t list
, size_t position
)
839 size_t count
= list
->count
;
840 gl_list_node_t removed_node
;
842 if (!(position
< count
))
843 /* Invalid argument. */
845 /* Here we know count > 0. */
846 if (position
<= ((count
- 1) / 2))
849 gl_list_node_t after_removed
;
852 for (; position
> 0; position
--)
854 removed_node
= node
->next
;
855 after_removed
= node
->next
->next
;
856 ASYNCSAFE(gl_list_node_t
) node
->next
= after_removed
;
857 after_removed
->prev
= node
;
862 gl_list_node_t before_removed
;
864 position
= count
- 1 - position
;
866 for (; position
> 0; position
--)
868 removed_node
= node
->prev
;
869 before_removed
= node
->prev
->prev
;
870 node
->prev
= before_removed
;
871 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= node
;
874 remove_from_bucket (list
, removed_node
);
878 if (list
->base
.dispose_fn
!= NULL
)
879 list
->base
.dispose_fn (removed_node
->value
);
885 gl_linked_remove (gl_list_t list
, const void *elt
)
887 gl_list_node_t node
= gl_linked_search_from_to (list
, 0, list
->count
, elt
);
890 return gl_linked_remove_node (list
, node
);
896 gl_linked_list_free (gl_list_t list
)
898 gl_listelement_dispose_fn dispose
= list
->base
.dispose_fn
;
901 for (node
= list
->root
.next
; node
!= &list
->root
; )
903 gl_list_node_t next
= node
->next
;
905 dispose (node
->value
);
915 /* --------------------- gl_list_iterator_t Data Type --------------------- */
917 static gl_list_iterator_t
918 gl_linked_iterator (gl_list_t list
)
920 gl_list_iterator_t result
;
922 result
.vtable
= list
->base
.vtable
;
924 result
.p
= list
->root
.next
;
925 result
.q
= &list
->root
;
926 #if defined GCC_LINT || defined lint
935 static gl_list_iterator_t
936 gl_linked_iterator_from_to (gl_list_t list
,
937 size_t start_index
, size_t end_index
)
939 gl_list_iterator_t result
;
942 if (!(start_index
<= end_index
&& end_index
<= list
->count
))
943 /* Invalid arguments. */
945 result
.vtable
= list
->base
.vtable
;
948 n2
= end_index
- start_index
;
949 n3
= list
->count
- end_index
;
950 /* Find the maximum among n1, n2, n3, so as to reduce the number of
951 loop iterations to n1 + n2 + n3 - max(n1,n2,n3). */
952 if (n1
> n2
&& n1
> n3
)
954 /* n1 is the maximum, use n2 and n3. */
959 for (i
= n3
; i
> 0; i
--)
962 for (i
= n2
; i
> 0; i
--)
968 /* n2 is the maximum, use n1 and n3. */
972 node
= list
->root
.next
;
973 for (i
= n1
; i
> 0; i
--)
978 for (i
= n3
; i
> 0; i
--)
984 /* n3 is the maximum, use n1 and n2. */
988 node
= list
->root
.next
;
989 for (i
= n1
; i
> 0; i
--)
992 for (i
= n2
; i
> 0; i
--)
997 #if defined GCC_LINT || defined lint
1007 gl_linked_iterator_next (gl_list_iterator_t
*iterator
,
1008 const void **eltp
, gl_list_node_t
*nodep
)
1010 if (iterator
->p
!= iterator
->q
)
1012 gl_list_node_t node
= (gl_list_node_t
) iterator
->p
;
1013 *eltp
= node
->value
;
1016 iterator
->p
= node
->next
;
1024 gl_linked_iterator_free (gl_list_iterator_t
*iterator
)
1028 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
1030 static gl_list_node_t _GL_ATTRIBUTE_PURE
1031 gl_linked_sortedlist_search (gl_list_t list
, gl_listelement_compar_fn compar
,
1034 gl_list_node_t node
;
1036 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1038 int cmp
= compar (node
->value
, elt
);
1048 static gl_list_node_t _GL_ATTRIBUTE_PURE
1049 gl_linked_sortedlist_search_from_to (gl_list_t list
,
1050 gl_listelement_compar_fn compar
,
1051 size_t low
, size_t high
,
1054 size_t count
= list
->count
;
1056 if (!(low
<= high
&& high
<= list
->count
))
1057 /* Invalid arguments. */
1063 /* Here we know low < count. */
1064 size_t position
= low
;
1065 gl_list_node_t node
;
1067 if (position
<= ((count
- 1) / 2))
1069 node
= list
->root
.next
;
1070 for (; position
> 0; position
--)
1075 position
= count
- 1 - position
;
1076 node
= list
->root
.prev
;
1077 for (; position
> 0; position
--)
1083 int cmp
= compar (node
->value
, elt
);
1096 static size_t _GL_ATTRIBUTE_PURE
1097 gl_linked_sortedlist_indexof (gl_list_t list
, gl_listelement_compar_fn compar
,
1100 gl_list_node_t node
;
1103 for (node
= list
->root
.next
, index
= 0;
1104 node
!= &list
->root
;
1105 node
= node
->next
, index
++)
1107 int cmp
= compar (node
->value
, elt
);
1114 return (size_t)(-1);
1117 static size_t _GL_ATTRIBUTE_PURE
1118 gl_linked_sortedlist_indexof_from_to (gl_list_t list
,
1119 gl_listelement_compar_fn compar
,
1120 size_t low
, size_t high
,
1123 size_t count
= list
->count
;
1125 if (!(low
<= high
&& high
<= list
->count
))
1126 /* Invalid arguments. */
1132 /* Here we know low < count. */
1134 size_t position
= low
;
1135 gl_list_node_t node
;
1137 if (position
<= ((count
- 1) / 2))
1139 node
= list
->root
.next
;
1140 for (; position
> 0; position
--)
1145 position
= count
- 1 - position
;
1146 node
= list
->root
.prev
;
1147 for (; position
> 0; position
--)
1153 int cmp
= compar (node
->value
, elt
);
1164 return (size_t)(-1);
1167 static gl_list_node_t
1168 gl_linked_sortedlist_nx_add (gl_list_t list
, gl_listelement_compar_fn compar
,
1171 gl_list_node_t node
;
1173 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1174 if (compar (node
->value
, elt
) >= 0)
1175 return gl_linked_nx_add_before (list
, node
, elt
);
1176 return gl_linked_nx_add_last (list
, elt
);
1180 gl_linked_sortedlist_remove (gl_list_t list
, gl_listelement_compar_fn compar
,
1183 gl_list_node_t node
;
1185 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1187 int cmp
= compar (node
->value
, elt
);
1192 return gl_linked_remove_node (list
, node
);