1 /* Sequential list data type implemented by a linked list.
2 Copyright (C) 2006-2020 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_ATTRIBUTE_MAYBE_UNUSED
,
180 gl_linked_node_nx_set_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED
,
185 if (elt
!= node
->value
)
187 size_t new_hashcode
=
188 (list
->base
.hashcode_fn
!= NULL
189 ? list
->base
.hashcode_fn (elt
)
190 : (size_t)(uintptr_t) elt
);
192 if (new_hashcode
!= node
->h
.hashcode
)
194 remove_from_bucket (list
, node
);
196 node
->h
.hashcode
= new_hashcode
;
197 if (add_to_bucket (list
, node
) < 0)
199 /* Out of memory. We removed node from a bucket but cannot add
200 it to another bucket. In order to avoid inconsistencies, we
201 must remove node entirely from the list. */
202 gl_list_node_t before_removed
= node
->prev
;
203 gl_list_node_t after_removed
= node
->next
;
204 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= after_removed
;
205 after_removed
->prev
= before_removed
;
220 static gl_list_node_t _GL_ATTRIBUTE_PURE
221 gl_linked_next_node (gl_list_t list
, gl_list_node_t node
)
223 return (node
->next
!= &list
->root
? node
->next
: NULL
);
226 static gl_list_node_t _GL_ATTRIBUTE_PURE
227 gl_linked_previous_node (gl_list_t list
, gl_list_node_t node
)
229 return (node
->prev
!= &list
->root
? node
->prev
: NULL
);
232 static const void * _GL_ATTRIBUTE_PURE
233 gl_linked_get_at (gl_list_t list
, size_t position
)
235 size_t count
= list
->count
;
238 if (!(position
< count
))
239 /* Invalid argument. */
241 /* Here we know count > 0. */
242 if (position
<= ((count
- 1) / 2))
244 node
= list
->root
.next
;
245 for (; position
> 0; position
--)
250 position
= count
- 1 - position
;
251 node
= list
->root
.prev
;
252 for (; position
> 0; position
--)
258 static gl_list_node_t
259 gl_linked_nx_set_at (gl_list_t list
, size_t position
, const void *elt
)
261 size_t count
= list
->count
;
264 if (!(position
< count
))
265 /* Invalid argument. */
267 /* Here we know count > 0. */
268 if (position
<= ((count
- 1) / 2))
270 node
= list
->root
.next
;
271 for (; position
> 0; position
--)
276 position
= count
- 1 - position
;
277 node
= list
->root
.prev
;
278 for (; position
> 0; position
--)
282 if (elt
!= node
->value
)
284 size_t new_hashcode
=
285 (list
->base
.hashcode_fn
!= NULL
286 ? list
->base
.hashcode_fn (elt
)
287 : (size_t)(uintptr_t) elt
);
289 if (new_hashcode
!= node
->h
.hashcode
)
291 remove_from_bucket (list
, node
);
293 node
->h
.hashcode
= new_hashcode
;
294 if (add_to_bucket (list
, node
) < 0)
296 /* Out of memory. We removed node from a bucket but cannot add
297 it to another bucket. In order to avoid inconsistencies, we
298 must remove node entirely from the list. */
299 gl_list_node_t before_removed
= node
->prev
;
300 gl_list_node_t after_removed
= node
->next
;
301 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= after_removed
;
302 after_removed
->prev
= before_removed
;
317 static gl_list_node_t _GL_ATTRIBUTE_PURE
318 gl_linked_search_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
321 size_t count
= list
->count
;
323 if (!(start_index
<= end_index
&& end_index
<= count
))
324 /* Invalid arguments. */
329 (list
->base
.hashcode_fn
!= NULL
330 ? list
->base
.hashcode_fn (elt
)
331 : (size_t)(uintptr_t) elt
);
332 size_t bucket
= hashcode
% list
->table_size
;
333 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
335 if (!list
->base
.allow_duplicates
)
337 /* Look for the first match in the hash bucket. */
338 gl_list_node_t found
= NULL
;
341 for (node
= (gl_list_node_t
) list
->table
[bucket
];
343 node
= (gl_list_node_t
) node
->h
.hash_next
)
344 if (node
->h
.hashcode
== hashcode
346 ? equals (elt
, node
->value
)
347 : elt
== node
->value
))
353 /* Look whether found's index is < start_index. */
354 for (node
= list
->root
.next
; ; node
= node
->next
)
358 if (--start_index
== 0)
361 if (end_index
< count
)
362 /* Look whether found's index is >= end_index. */
364 end_index
= count
- end_index
;
365 for (node
= list
->root
.prev
; ; node
= node
->prev
)
369 if (--end_index
== 0)
377 /* Look whether there is more than one match in the hash bucket. */
378 bool multiple_matches
= false;
379 gl_list_node_t first_match
= NULL
;
382 for (node
= (gl_list_node_t
) list
->table
[bucket
];
384 node
= (gl_list_node_t
) node
->h
.hash_next
)
385 if (node
->h
.hashcode
== hashcode
387 ? equals (elt
, node
->value
)
388 : elt
== node
->value
))
390 if (first_match
== NULL
)
394 multiple_matches
= true;
398 if (multiple_matches
)
400 /* We need the match with the smallest index. But we don't have
401 a fast mapping node -> index. So we have to walk the list. */
402 end_index
-= start_index
;
403 node
= list
->root
.next
;
404 for (; start_index
> 0; start_index
--)
409 node
= node
->next
, end_index
--)
410 if (node
->h
.hashcode
== hashcode
412 ? equals (elt
, node
->value
)
413 : elt
== node
->value
))
415 /* The matches must have all been at indices < start_index or
422 /* Look whether first_match's index is < start_index. */
423 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
425 if (node
== first_match
)
427 if (--start_index
== 0)
430 if (end_index
< list
->count
)
431 /* Look whether first_match's index is >= end_index. */
433 end_index
= list
->count
- end_index
;
434 for (node
= list
->root
.prev
; ; node
= node
->prev
)
436 if (node
== first_match
)
438 if (--end_index
== 0)
446 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
447 gl_list_node_t node
= list
->root
.next
;
449 end_index
-= start_index
;
450 for (; start_index
> 0; start_index
--)
455 for (; end_index
> 0; node
= node
->next
, end_index
--)
456 if (equals (elt
, node
->value
))
461 for (; end_index
> 0; node
= node
->next
, end_index
--)
462 if (elt
== node
->value
)
470 static size_t _GL_ATTRIBUTE_PURE
471 gl_linked_indexof_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
474 size_t count
= list
->count
;
476 if (!(start_index
<= end_index
&& end_index
<= count
))
477 /* Invalid arguments. */
481 /* Here the hash table doesn't help much. It only allows us to minimize
482 the number of equals() calls, by looking up first the node and then
485 (list
->base
.hashcode_fn
!= NULL
486 ? list
->base
.hashcode_fn (elt
)
487 : (size_t)(uintptr_t) elt
);
488 size_t bucket
= hashcode
% list
->table_size
;
489 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
492 /* First step: Look up the node. */
493 if (!list
->base
.allow_duplicates
)
495 /* Look for the first match in the hash bucket. */
496 for (node
= (gl_list_node_t
) list
->table
[bucket
];
498 node
= (gl_list_node_t
) node
->h
.hash_next
)
499 if (node
->h
.hashcode
== hashcode
501 ? equals (elt
, node
->value
)
502 : elt
== node
->value
))
507 /* Look whether there is more than one match in the hash bucket. */
508 bool multiple_matches
= false;
509 gl_list_node_t first_match
= NULL
;
511 for (node
= (gl_list_node_t
) list
->table
[bucket
];
513 node
= (gl_list_node_t
) node
->h
.hash_next
)
514 if (node
->h
.hashcode
== hashcode
516 ? equals (elt
, node
->value
)
517 : elt
== node
->value
))
519 if (first_match
== NULL
)
523 multiple_matches
= true;
527 if (multiple_matches
)
529 /* We need the match with the smallest index. But we don't have
530 a fast mapping node -> index. So we have to walk the list. */
534 node
= list
->root
.next
;
535 for (; start_index
> 0; start_index
--)
540 node
= node
->next
, index
++)
541 if (node
->h
.hashcode
== hashcode
543 ? equals (elt
, node
->value
)
544 : elt
== node
->value
))
546 /* The matches must have all been at indices < start_index or
553 /* Second step: Look up the index of the node. */
560 for (; node
->prev
!= &list
->root
; node
= node
->prev
)
563 if (index
>= start_index
&& index
< end_index
)
569 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
570 size_t index
= start_index
;
571 gl_list_node_t node
= list
->root
.next
;
573 for (; start_index
> 0; start_index
--)
580 node
= node
->next
, index
++)
581 if (equals (elt
, node
->value
))
588 node
= node
->next
, index
++)
589 if (elt
== node
->value
)
597 static gl_list_node_t
598 gl_linked_nx_add_first (gl_list_t list
, const void *elt
)
600 gl_list_node_t node
=
601 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
606 ASYNCSAFE(const void *) node
->value
= elt
;
609 (list
->base
.hashcode_fn
!= NULL
610 ? list
->base
.hashcode_fn (node
->value
)
611 : (size_t)(uintptr_t) node
->value
);
613 /* Add node to the hash table. */
614 if (add_to_bucket (list
, node
) < 0)
621 /* Add node to the list. */
622 node
->prev
= &list
->root
;
623 ASYNCSAFE(gl_list_node_t
) node
->next
= list
->root
.next
;
624 node
->next
->prev
= node
;
625 ASYNCSAFE(gl_list_node_t
) list
->root
.next
= node
;
629 hash_resize_after_add (list
);
635 static gl_list_node_t
636 gl_linked_nx_add_last (gl_list_t list
, const void *elt
)
638 gl_list_node_t node
=
639 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
644 ASYNCSAFE(const void *) node
->value
= elt
;
647 (list
->base
.hashcode_fn
!= NULL
648 ? list
->base
.hashcode_fn (node
->value
)
649 : (size_t)(uintptr_t) node
->value
);
651 /* Add node to the hash table. */
652 if (add_to_bucket (list
, node
) < 0)
659 /* Add node to the list. */
660 ASYNCSAFE(gl_list_node_t
) node
->next
= &list
->root
;
661 node
->prev
= list
->root
.prev
;
662 ASYNCSAFE(gl_list_node_t
) node
->prev
->next
= node
;
663 list
->root
.prev
= node
;
667 hash_resize_after_add (list
);
673 static gl_list_node_t
674 gl_linked_nx_add_before (gl_list_t list
, gl_list_node_t node
, const void *elt
)
676 gl_list_node_t new_node
=
677 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
679 if (new_node
== NULL
)
682 ASYNCSAFE(const void *) new_node
->value
= elt
;
684 new_node
->h
.hashcode
=
685 (list
->base
.hashcode_fn
!= NULL
686 ? list
->base
.hashcode_fn (new_node
->value
)
687 : (size_t)(uintptr_t) new_node
->value
);
689 /* Add new_node to the hash table. */
690 if (add_to_bucket (list
, new_node
) < 0)
697 /* Add new_node to the list. */
698 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
;
699 new_node
->prev
= node
->prev
;
700 ASYNCSAFE(gl_list_node_t
) new_node
->prev
->next
= new_node
;
701 node
->prev
= new_node
;
705 hash_resize_after_add (list
);
711 static gl_list_node_t
712 gl_linked_nx_add_after (gl_list_t list
, gl_list_node_t node
, const void *elt
)
714 gl_list_node_t new_node
=
715 (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
717 if (new_node
== NULL
)
720 ASYNCSAFE(const void *) new_node
->value
= elt
;
722 new_node
->h
.hashcode
=
723 (list
->base
.hashcode_fn
!= NULL
724 ? list
->base
.hashcode_fn (new_node
->value
)
725 : (size_t)(uintptr_t) new_node
->value
);
727 /* Add new_node to the hash table. */
728 if (add_to_bucket (list
, new_node
) < 0)
735 /* Add new_node to the list. */
736 new_node
->prev
= node
;
737 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
->next
;
738 new_node
->next
->prev
= new_node
;
739 ASYNCSAFE(gl_list_node_t
) node
->next
= new_node
;
743 hash_resize_after_add (list
);
749 static gl_list_node_t
750 gl_linked_nx_add_at (gl_list_t list
, size_t position
, const void *elt
)
752 size_t count
= list
->count
;
753 gl_list_node_t new_node
;
755 if (!(position
<= count
))
756 /* Invalid argument. */
759 new_node
= (struct gl_list_node_impl
*) malloc (sizeof (struct gl_list_node_impl
));
760 if (new_node
== NULL
)
763 ASYNCSAFE(const void *) new_node
->value
= elt
;
765 new_node
->h
.hashcode
=
766 (list
->base
.hashcode_fn
!= NULL
767 ? list
->base
.hashcode_fn (new_node
->value
)
768 : (size_t)(uintptr_t) new_node
->value
);
770 /* Add new_node to the hash table. */
771 if (add_to_bucket (list
, new_node
) < 0)
778 /* Add new_node to the list. */
779 if (position
<= (count
/ 2))
784 for (; position
> 0; position
--)
786 new_node
->prev
= node
;
787 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
->next
;
788 new_node
->next
->prev
= new_node
;
789 ASYNCSAFE(gl_list_node_t
) node
->next
= new_node
;
795 position
= count
- position
;
797 for (; position
> 0; position
--)
799 ASYNCSAFE(gl_list_node_t
) new_node
->next
= node
;
800 new_node
->prev
= node
->prev
;
801 ASYNCSAFE(gl_list_node_t
) new_node
->prev
->next
= new_node
;
802 node
->prev
= new_node
;
807 hash_resize_after_add (list
);
814 gl_linked_remove_node (gl_list_t list
, gl_list_node_t node
)
820 /* Remove node from the hash table. */
821 remove_from_bucket (list
, node
);
824 /* Remove node from the list. */
828 ASYNCSAFE(gl_list_node_t
) prev
->next
= next
;
832 if (list
->base
.dispose_fn
!= NULL
)
833 list
->base
.dispose_fn (node
->value
);
839 gl_linked_remove_at (gl_list_t list
, size_t position
)
841 size_t count
= list
->count
;
842 gl_list_node_t removed_node
;
844 if (!(position
< count
))
845 /* Invalid argument. */
847 /* Here we know count > 0. */
848 if (position
<= ((count
- 1) / 2))
851 gl_list_node_t after_removed
;
854 for (; position
> 0; position
--)
856 removed_node
= node
->next
;
857 after_removed
= node
->next
->next
;
858 ASYNCSAFE(gl_list_node_t
) node
->next
= after_removed
;
859 after_removed
->prev
= node
;
864 gl_list_node_t before_removed
;
866 position
= count
- 1 - position
;
868 for (; position
> 0; position
--)
870 removed_node
= node
->prev
;
871 before_removed
= node
->prev
->prev
;
872 node
->prev
= before_removed
;
873 ASYNCSAFE(gl_list_node_t
) before_removed
->next
= node
;
876 remove_from_bucket (list
, removed_node
);
880 if (list
->base
.dispose_fn
!= NULL
)
881 list
->base
.dispose_fn (removed_node
->value
);
887 gl_linked_remove (gl_list_t list
, const void *elt
)
889 gl_list_node_t node
= gl_linked_search_from_to (list
, 0, list
->count
, elt
);
892 return gl_linked_remove_node (list
, node
);
898 gl_linked_list_free (gl_list_t list
)
900 gl_listelement_dispose_fn dispose
= list
->base
.dispose_fn
;
903 for (node
= list
->root
.next
; node
!= &list
->root
; )
905 gl_list_node_t next
= node
->next
;
907 dispose (node
->value
);
917 /* --------------------- gl_list_iterator_t Data Type --------------------- */
919 static gl_list_iterator_t
920 gl_linked_iterator (gl_list_t list
)
922 gl_list_iterator_t result
;
924 result
.vtable
= list
->base
.vtable
;
926 result
.p
= list
->root
.next
;
927 result
.q
= &list
->root
;
928 #if defined GCC_LINT || defined lint
937 static gl_list_iterator_t
938 gl_linked_iterator_from_to (gl_list_t list
,
939 size_t start_index
, size_t end_index
)
941 gl_list_iterator_t result
;
944 if (!(start_index
<= end_index
&& end_index
<= list
->count
))
945 /* Invalid arguments. */
947 result
.vtable
= list
->base
.vtable
;
950 n2
= end_index
- start_index
;
951 n3
= list
->count
- end_index
;
952 /* Find the maximum among n1, n2, n3, so as to reduce the number of
953 loop iterations to n1 + n2 + n3 - max(n1,n2,n3). */
954 if (n1
> n2
&& n1
> n3
)
956 /* n1 is the maximum, use n2 and n3. */
961 for (i
= n3
; i
> 0; i
--)
964 for (i
= n2
; i
> 0; i
--)
970 /* n2 is the maximum, use n1 and n3. */
974 node
= list
->root
.next
;
975 for (i
= n1
; i
> 0; i
--)
980 for (i
= n3
; i
> 0; i
--)
986 /* n3 is the maximum, use n1 and n2. */
990 node
= list
->root
.next
;
991 for (i
= n1
; i
> 0; i
--)
994 for (i
= n2
; i
> 0; i
--)
999 #if defined GCC_LINT || defined lint
1009 gl_linked_iterator_next (gl_list_iterator_t
*iterator
,
1010 const void **eltp
, gl_list_node_t
*nodep
)
1012 if (iterator
->p
!= iterator
->q
)
1014 gl_list_node_t node
= (gl_list_node_t
) iterator
->p
;
1015 *eltp
= node
->value
;
1018 iterator
->p
= node
->next
;
1026 gl_linked_iterator_free (gl_list_iterator_t
*iterator _GL_ATTRIBUTE_MAYBE_UNUSED
)
1030 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
1032 static gl_list_node_t _GL_ATTRIBUTE_PURE
1033 gl_linked_sortedlist_search (gl_list_t list
, gl_listelement_compar_fn compar
,
1036 gl_list_node_t node
;
1038 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1040 int cmp
= compar (node
->value
, elt
);
1050 static gl_list_node_t _GL_ATTRIBUTE_PURE
1051 gl_linked_sortedlist_search_from_to (gl_list_t list
,
1052 gl_listelement_compar_fn compar
,
1053 size_t low
, size_t high
,
1056 size_t count
= list
->count
;
1058 if (!(low
<= high
&& high
<= list
->count
))
1059 /* Invalid arguments. */
1065 /* Here we know low < count. */
1066 size_t position
= low
;
1067 gl_list_node_t node
;
1069 if (position
<= ((count
- 1) / 2))
1071 node
= list
->root
.next
;
1072 for (; position
> 0; position
--)
1077 position
= count
- 1 - position
;
1078 node
= list
->root
.prev
;
1079 for (; position
> 0; position
--)
1085 int cmp
= compar (node
->value
, elt
);
1098 static size_t _GL_ATTRIBUTE_PURE
1099 gl_linked_sortedlist_indexof (gl_list_t list
, gl_listelement_compar_fn compar
,
1102 gl_list_node_t node
;
1105 for (node
= list
->root
.next
, index
= 0;
1106 node
!= &list
->root
;
1107 node
= node
->next
, index
++)
1109 int cmp
= compar (node
->value
, elt
);
1116 return (size_t)(-1);
1119 static size_t _GL_ATTRIBUTE_PURE
1120 gl_linked_sortedlist_indexof_from_to (gl_list_t list
,
1121 gl_listelement_compar_fn compar
,
1122 size_t low
, size_t high
,
1125 size_t count
= list
->count
;
1127 if (!(low
<= high
&& high
<= list
->count
))
1128 /* Invalid arguments. */
1134 /* Here we know low < count. */
1136 size_t position
= low
;
1137 gl_list_node_t node
;
1139 if (position
<= ((count
- 1) / 2))
1141 node
= list
->root
.next
;
1142 for (; position
> 0; position
--)
1147 position
= count
- 1 - position
;
1148 node
= list
->root
.prev
;
1149 for (; position
> 0; position
--)
1155 int cmp
= compar (node
->value
, elt
);
1166 return (size_t)(-1);
1169 static gl_list_node_t
1170 gl_linked_sortedlist_nx_add (gl_list_t list
, gl_listelement_compar_fn compar
,
1173 gl_list_node_t node
;
1175 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1176 if (compar (node
->value
, elt
) >= 0)
1177 return gl_linked_nx_add_before (list
, node
, elt
);
1178 return gl_linked_nx_add_last (list
, elt
);
1182 gl_linked_sortedlist_remove (gl_list_t list
, gl_listelement_compar_fn compar
,
1185 gl_list_node_t node
;
1187 for (node
= list
->root
.next
; node
!= &list
->root
; node
= node
->next
)
1189 int cmp
= compar (node
->value
, elt
);
1194 return gl_linked_remove_node (list
, node
);