Coverage Report

Created: 2026-03-31 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/gl/gl_anytree_list2.h
Line
Count
Source
1
/* Sequential list data type implemented by a binary tree.
2
   Copyright (C) 2006-2026 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
/* Common code of gl_avltree_list.c, gl_rbtree_list.c,
19
                  gl_avltreehash_list.c, gl_rbtreehash_list.c.  */
20
21
static gl_list_t
22
gl_tree_nx_create_empty (gl_list_implementation_t implementation,
23
                         gl_listelement_equals_fn equals_fn,
24
                         gl_listelement_hashcode_fn hashcode_fn,
25
                         gl_listelement_dispose_fn dispose_fn,
26
                         bool allow_duplicates)
27
0
{
28
0
  struct gl_list_impl *list = (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
29
30
0
  if (list == NULL)
31
0
    return NULL;
32
33
0
  list->base.vtable = implementation;
34
0
  list->base.equals_fn = equals_fn;
35
0
  list->base.hashcode_fn = hashcode_fn;
36
0
  list->base.dispose_fn = dispose_fn;
37
0
  list->base.allow_duplicates = allow_duplicates;
38
#if WITH_HASHTABLE
39
  list->table_size = 11;
40
  list->table =
41
    (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t));
42
  if (list->table == NULL)
43
    goto fail;
44
#endif
45
0
  list->root = NULL;
46
47
0
  return list;
48
49
#if WITH_HASHTABLE
50
 fail:
51
  free (list);
52
  return NULL;
53
#endif
54
0
}
55
56
static size_t _GL_ATTRIBUTE_PURE
57
gl_tree_size (gl_list_t list)
58
0
{
59
0
  return (list->root != NULL ? list->root->branch_size : 0);
60
0
}
61
62
static const void * _GL_ATTRIBUTE_PURE
63
gl_tree_node_value (gl_list_t _GL_UNNAMED (list), gl_list_node_t node)
64
0
{
65
0
  return node->value;
66
0
}
67
68
static int
69
gl_tree_node_nx_set_value (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list,
70
                           gl_list_node_t node, const void *elt)
71
0
{
72
#if WITH_HASHTABLE
73
  if (elt != node->value)
74
    {
75
      size_t new_hashcode =
76
        (list->base.hashcode_fn != NULL
77
         ? list->base.hashcode_fn (elt)
78
         : (size_t)(uintptr_t) elt);
79
80
      if (new_hashcode != node->h.hashcode)
81
        {
82
          remove_from_bucket (list, node);
83
          node->value = elt;
84
          node->h.hashcode = new_hashcode;
85
          if (add_to_bucket (list, node) < 0)
86
            {
87
              /* Out of memory.  We removed node from a bucket but cannot add
88
                 it to another bucket.  In order to avoid inconsistencies, we
89
                 must remove node entirely from the list.  */
90
              gl_tree_remove_node_from_tree (list, node);
91
              free (node);
92
              return -1;
93
            }
94
        }
95
      else
96
        node->value = elt;
97
    }
98
#else
99
0
  node->value = elt;
100
0
#endif
101
0
  return 0;
102
0
}
103
104
static gl_list_node_t _GL_ATTRIBUTE_PURE
105
gl_tree_next_node (gl_list_t _GL_UNNAMED (list), gl_list_node_t node)
106
0
{
107
0
  if (node->right != NULL)
108
0
    {
109
0
      node = node->right;
110
0
      while (node->left != NULL)
111
0
        node = node->left;
112
0
    }
113
0
  else
114
0
    {
115
0
      while (node->parent != NULL && node->parent->right == node)
116
0
        node = node->parent;
117
0
      node = node->parent;
118
0
    }
119
0
  return node;
120
0
}
121
122
static gl_list_node_t _GL_ATTRIBUTE_PURE
123
gl_tree_previous_node (gl_list_t _GL_UNNAMED (list), gl_list_node_t node)
124
0
{
125
0
  if (node->left != NULL)
126
0
    {
127
0
      node = node->left;
128
0
      while (node->right != NULL)
129
0
        node = node->right;
130
0
    }
131
0
  else
132
0
    {
133
0
      while (node->parent != NULL && node->parent->left == node)
134
0
        node = node->parent;
135
0
      node = node->parent;
136
0
    }
137
0
  return node;
138
0
}
139
140
static gl_list_node_t _GL_ATTRIBUTE_PURE
141
gl_tree_first_node (gl_list_t list)
142
0
{
143
0
  gl_list_node_t node = list->root;
144
145
0
  if (node != NULL)
146
0
    {
147
0
      while (node->left != NULL)
148
0
        node = node->left;
149
0
    }
150
0
  return node;
151
0
}
152
153
static gl_list_node_t _GL_ATTRIBUTE_PURE
154
gl_tree_last_node (gl_list_t list)
155
0
{
156
0
  gl_list_node_t node = list->root;
157
158
0
  if (node != NULL)
159
0
    {
160
0
      while (node->right != NULL)
161
0
        node = node->right;
162
0
    }
163
0
  return node;
164
0
}
165
166
/* Returns the node at the given position < gl_tree_size (list).  */
167
static gl_list_node_t _GL_ATTRIBUTE_PURE
168
node_at (gl_list_node_t root, size_t position)
169
0
{
170
  /* Here we know that root != NULL.  */
171
0
  gl_list_node_t node = root;
172
173
0
  for (;;)
174
0
    {
175
0
      if (node->left != NULL)
176
0
        {
177
0
          if (position < node->left->branch_size)
178
0
            {
179
0
              node = node->left;
180
0
              continue;
181
0
            }
182
0
          position -= node->left->branch_size;
183
0
        }
184
0
      if (position == 0)
185
0
        break;
186
0
      position--;
187
0
      node = node->right;
188
0
    }
189
0
  return node;
190
0
}
191
192
static const void * _GL_ATTRIBUTE_PURE
193
gl_tree_get_at (gl_list_t list, size_t position)
194
0
{
195
0
  gl_list_node_t node = list->root;
196
197
0
  if (!(node != NULL && position < node->branch_size))
198
    /* Invalid argument.  */
199
0
    abort ();
200
0
  node = node_at (node, position);
201
0
  return node->value;
202
0
}
203
204
static gl_list_node_t
205
gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt)
206
0
{
207
0
  gl_list_node_t node = list->root;
208
209
0
  if (!(node != NULL && position < node->branch_size))
210
    /* Invalid argument.  */
211
0
    abort ();
212
0
  node = node_at (node, position);
213
#if WITH_HASHTABLE
214
  if (elt != node->value)
215
    {
216
      size_t new_hashcode =
217
        (list->base.hashcode_fn != NULL
218
         ? list->base.hashcode_fn (elt)
219
         : (size_t)(uintptr_t) elt);
220
221
      if (new_hashcode != node->h.hashcode)
222
        {
223
          remove_from_bucket (list, node);
224
          node->value = elt;
225
          node->h.hashcode = new_hashcode;
226
          if (add_to_bucket (list, node) < 0)
227
            {
228
              /* Out of memory.  We removed node from a bucket but cannot add
229
                 it to another bucket.  In order to avoid inconsistencies, we
230
                 must remove node entirely from the list.  */
231
              gl_tree_remove_node_from_tree (list, node);
232
              free (node);
233
              return NULL;
234
            }
235
        }
236
      else
237
        node->value = elt;
238
    }
239
#else
240
0
  node->value = elt;
241
0
#endif
242
0
  return node;
243
0
}
244
245
#if !WITH_HASHTABLE
246
247
static gl_list_node_t _GL_ATTRIBUTE_PURE
248
gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
249
                        const void *elt)
250
0
{
251
0
  if (!(start_index <= end_index
252
0
        && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
253
    /* Invalid arguments.  */
254
0
    abort ();
255
0
  {
256
0
    gl_listelement_equals_fn equals = list->base.equals_fn;
257
    /* Iterate across all elements.  */
258
0
    gl_list_node_t node = list->root;
259
0
    iterstack_t stack;
260
0
    iterstack_item_t *stack_ptr = &stack[0];
261
0
    size_t index = 0;
262
263
0
    if (start_index == 0)
264
0
      {
265
        /* Consider all elements.  */
266
0
        for (;;)
267
0
          {
268
            /* Descend on left branch.  */
269
0
            for (;;)
270
0
              {
271
0
                if (node == NULL)
272
0
                  break;
273
0
                stack_ptr->node = node;
274
0
                stack_ptr->rightp = 0;
275
0
                node = node->left;
276
0
                stack_ptr++;
277
0
              }
278
            /* Climb up again.  */
279
0
            for (;;)
280
0
              {
281
0
                if (stack_ptr == &stack[0])
282
0
                  return NULL;
283
0
                stack_ptr--;
284
0
                if (!stack_ptr->rightp)
285
0
                  break;
286
0
              }
287
0
            node = stack_ptr->node;
288
            /* Test against current element.  */
289
0
            if (equals != NULL ? equals (elt, node->value) : elt == node->value)
290
0
              return node;
291
0
            index++;
292
0
            if (index >= end_index)
293
0
              return NULL;
294
            /* Descend on right branch.  */
295
0
            stack_ptr->rightp = 1;
296
0
            node = node->right;
297
0
            stack_ptr++;
298
0
          }
299
0
      }
300
0
    else
301
0
      {
302
        /* Consider only elements at indices >= start_index.
303
           In this case, rightp contains the difference between the start_index
304
           for the parent node and the one for the child node (0 when the child
305
           node is the parent's left child, > 0 when the child is the parent's
306
           right child).  */
307
0
        for (;;)
308
0
          {
309
            /* Descend on left branch.  */
310
0
            for (;;)
311
0
              {
312
0
                if (node == NULL)
313
0
                  break;
314
0
                if (node->branch_size <= start_index)
315
0
                  break;
316
0
                stack_ptr->node = node;
317
0
                stack_ptr->rightp = 0;
318
0
                node = node->left;
319
0
                stack_ptr++;
320
0
              }
321
            /* Climb up again.  */
322
0
            for (;;)
323
0
              {
324
0
                if (stack_ptr == &stack[0])
325
0
                  return NULL;
326
0
                stack_ptr--;
327
0
                if (!stack_ptr->rightp)
328
0
                  break;
329
0
                start_index += stack_ptr->rightp;
330
0
              }
331
0
            node = stack_ptr->node;
332
0
            {
333
0
              size_t left_branch_size1 =
334
0
                (node->left != NULL ? node->left->branch_size : 0) + 1;
335
0
              if (start_index < left_branch_size1)
336
0
                {
337
                  /* Test against current element.  */
338
0
                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
339
0
                    return node;
340
                  /* Now that we have considered all indices < left_branch_size1,
341
                     we can increment start_index.  */
342
0
                  start_index = left_branch_size1;
343
0
                }
344
0
              index++;
345
0
              if (index >= end_index)
346
0
                return NULL;
347
              /* Descend on right branch.  */
348
0
              start_index -= left_branch_size1;
349
0
              stack_ptr->rightp = left_branch_size1;
350
0
            }
351
0
            node = node->right;
352
0
            stack_ptr++;
353
0
          }
354
0
      }
355
0
  }
356
0
}
357
358
static size_t _GL_ATTRIBUTE_PURE
359
gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
360
                         const void *elt)
361
0
{
362
0
  if (!(start_index <= end_index
363
0
        && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
364
    /* Invalid arguments.  */
365
0
    abort ();
366
0
  {
367
0
    gl_listelement_equals_fn equals = list->base.equals_fn;
368
    /* Iterate across all elements.  */
369
0
    gl_list_node_t node = list->root;
370
0
    iterstack_t stack;
371
0
    iterstack_item_t *stack_ptr = &stack[0];
372
0
    size_t index = 0;
373
374
0
    if (start_index == 0)
375
0
      {
376
        /* Consider all elements.  */
377
0
        for (;;)
378
0
          {
379
            /* Descend on left branch.  */
380
0
            for (;;)
381
0
              {
382
0
                if (node == NULL)
383
0
                  break;
384
0
                stack_ptr->node = node;
385
0
                stack_ptr->rightp = 0;
386
0
                node = node->left;
387
0
                stack_ptr++;
388
0
              }
389
            /* Climb up again.  */
390
0
            for (;;)
391
0
              {
392
0
                if (stack_ptr == &stack[0])
393
0
                  return (size_t)(-1);
394
0
                stack_ptr--;
395
0
                if (!stack_ptr->rightp)
396
0
                  break;
397
0
              }
398
0
            node = stack_ptr->node;
399
            /* Test against current element.  */
400
0
            if (equals != NULL ? equals (elt, node->value) : elt == node->value)
401
0
              return index;
402
0
            index++;
403
0
            if (index >= end_index)
404
0
              return (size_t)(-1);
405
            /* Descend on right branch.  */
406
0
            stack_ptr->rightp = 1;
407
0
            node = node->right;
408
0
            stack_ptr++;
409
0
          }
410
0
      }
411
0
    else
412
0
      {
413
        /* Consider only elements at indices >= start_index.
414
           In this case, rightp contains the difference between the start_index
415
           for the parent node and the one for the child node (0 when the child
416
           node is the parent's left child, > 0 when the child is the parent's
417
           right child).  */
418
0
        for (;;)
419
0
          {
420
            /* Descend on left branch.  */
421
0
            for (;;)
422
0
              {
423
0
                if (node == NULL)
424
0
                  break;
425
0
                if (node->branch_size <= start_index)
426
0
                  break;
427
0
                stack_ptr->node = node;
428
0
                stack_ptr->rightp = 0;
429
0
                node = node->left;
430
0
                stack_ptr++;
431
0
              }
432
            /* Climb up again.  */
433
0
            for (;;)
434
0
              {
435
0
                if (stack_ptr == &stack[0])
436
0
                  return (size_t)(-1);
437
0
                stack_ptr--;
438
0
                if (!stack_ptr->rightp)
439
0
                  break;
440
0
                start_index += stack_ptr->rightp;
441
0
              }
442
0
            node = stack_ptr->node;
443
0
            {
444
0
              size_t left_branch_size1 =
445
0
                (node->left != NULL ? node->left->branch_size : 0) + 1;
446
0
              if (start_index < left_branch_size1)
447
0
                {
448
                  /* Test against current element.  */
449
0
                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
450
0
                    return index;
451
                  /* Now that we have considered all indices < left_branch_size1,
452
                     we can increment start_index.  */
453
0
                  start_index = left_branch_size1;
454
0
                }
455
0
              index++;
456
0
              if (index >= end_index)
457
0
                return (size_t)(-1);
458
              /* Descend on right branch.  */
459
0
              start_index -= left_branch_size1;
460
0
              stack_ptr->rightp = left_branch_size1;
461
0
            }
462
0
            node = node->right;
463
0
            stack_ptr++;
464
0
          }
465
0
      }
466
0
  }
467
0
}
468
469
#endif
470
471
static gl_list_node_t
472
gl_tree_nx_add_at (gl_list_t list, size_t position, const void *elt)
473
0
{
474
0
  size_t count = (list->root != NULL ? list->root->branch_size : 0);
475
476
0
  if (!(position <= count))
477
    /* Invalid argument.  */
478
0
    abort ();
479
0
  if (position == count)
480
0
    return gl_tree_nx_add_last (list, elt);
481
0
  else
482
0
    return gl_tree_nx_add_before (list, node_at (list->root, position), elt);
483
0
}
484
485
static bool
486
gl_tree_remove_node (gl_list_t list, gl_list_node_t node)
487
0
{
488
#if WITH_HASHTABLE
489
  /* Remove node from the hash table.
490
     Note that this is only possible _before_ the node is removed from the
491
     tree structure, because remove_from_bucket() uses node_position().  */
492
  remove_from_bucket (list, node);
493
#endif
494
495
0
  gl_tree_remove_node_from_tree (list, node);
496
497
0
  if (list->base.dispose_fn != NULL)
498
0
    list->base.dispose_fn (node->value);
499
0
  free (node);
500
0
  return true;
501
0
}
502
503
static bool
504
gl_tree_remove_at (gl_list_t list, size_t position)
505
0
{
506
0
  gl_list_node_t node = list->root;
507
508
0
  if (!(node != NULL && position < node->branch_size))
509
    /* Invalid argument.  */
510
0
    abort ();
511
0
  node = node_at (node, position);
512
0
  return gl_tree_remove_node (list, node);
513
0
}
514
515
static bool
516
gl_tree_remove (gl_list_t list, const void *elt)
517
0
{
518
0
  if (list->root != NULL)
519
0
    {
520
0
      gl_list_node_t node =
521
0
        gl_tree_search_from_to (list, 0, list->root->branch_size, elt);
522
523
0
      if (node != NULL)
524
0
        return gl_tree_remove_node (list, node);
525
0
    }
526
0
  return false;
527
0
}
528
529
#if !WITH_HASHTABLE
530
531
static void
532
gl_tree_list_free (gl_list_t list)
533
0
{
534
  /* Iterate across all elements in post-order.  */
535
0
  gl_list_node_t node = list->root;
536
0
  iterstack_t stack;
537
0
  iterstack_item_t *stack_ptr = &stack[0];
538
539
0
  for (;;)
540
0
    {
541
      /* Descend on left branch.  */
542
0
      for (;;)
543
0
        {
544
0
          if (node == NULL)
545
0
            break;
546
0
          stack_ptr->node = node;
547
0
          stack_ptr->rightp = false;
548
0
          node = node->left;
549
0
          stack_ptr++;
550
0
        }
551
      /* Climb up again.  */
552
0
      for (;;)
553
0
        {
554
0
          if (stack_ptr == &stack[0])
555
0
            goto done_iterate;
556
0
          stack_ptr--;
557
0
          node = stack_ptr->node;
558
0
          if (!stack_ptr->rightp)
559
0
            break;
560
          /* Free the current node.  */
561
0
          if (list->base.dispose_fn != NULL)
562
0
            list->base.dispose_fn (node->value);
563
0
          free (node);
564
0
        }
565
      /* Descend on right branch.  */
566
0
      stack_ptr->rightp = true;
567
0
      node = node->right;
568
0
      stack_ptr++;
569
0
    }
570
0
 done_iterate:
571
0
  free (list);
572
0
}
573
574
#endif
575
576
/* --------------------- gl_list_iterator_t Data Type --------------------- */
577
578
static gl_list_iterator_t _GL_ATTRIBUTE_PURE
579
gl_tree_iterator (gl_list_t list)
580
0
{
581
0
  gl_list_iterator_t result;
582
583
0
  result.vtable = list->base.vtable;
584
0
  result.list = list;
585
0
  {
586
    /* Start node is the leftmost node.  */
587
0
    gl_list_node_t node = list->root;
588
0
    if (node != NULL)
589
0
      while (node->left != NULL)
590
0
        node = node->left;
591
0
    result.p = node;
592
0
  }
593
  /* End point is past the rightmost node.  */
594
0
  result.q = NULL;
595
#if defined GCC_LINT || defined lint
596
  result.i = 0;
597
  result.j = 0;
598
  result.count = 0;
599
#endif
600
601
0
  return result;
602
0
}
603
604
static gl_list_iterator_t _GL_ATTRIBUTE_PURE
605
gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
606
0
{
607
0
  size_t count = (list->root != NULL ? list->root->branch_size : 0);
608
0
  gl_list_iterator_t result;
609
610
0
  if (!(start_index <= end_index && end_index <= count))
611
    /* Invalid arguments.  */
612
0
    abort ();
613
0
  result.vtable = list->base.vtable;
614
0
  result.list = list;
615
  /* Start node is the node at position start_index.  */
616
0
  result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
617
  /* End point is the node at position end_index.  */
618
0
  result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
619
#if defined GCC_LINT || defined lint
620
  result.i = 0;
621
  result.j = 0;
622
  result.count = 0;
623
#endif
624
625
0
  return result;
626
0
}
627
628
static bool
629
gl_tree_iterator_next (gl_list_iterator_t *iterator,
630
                       const void **eltp, gl_list_node_t *nodep)
631
0
{
632
0
  if (iterator->p != iterator->q)
633
0
    {
634
0
      gl_list_node_t node = (gl_list_node_t) iterator->p;
635
0
      *eltp = node->value;
636
0
      if (nodep != NULL)
637
0
        *nodep = node;
638
      /* Advance to the next node.  */
639
0
      if (node->right != NULL)
640
0
        {
641
0
          node = node->right;
642
0
          while (node->left != NULL)
643
0
            node = node->left;
644
0
        }
645
0
      else
646
0
        {
647
0
          while (node->parent != NULL && node->parent->right == node)
648
0
            node = node->parent;
649
0
          node = node->parent;
650
0
        }
651
0
      iterator->p = node;
652
0
      return true;
653
0
    }
654
0
  else
655
0
    return false;
656
0
}
657
658
static void
659
gl_tree_iterator_free (gl_list_iterator_t *_GL_UNNAMED (iterator))
660
0
{
661
0
}
662
663
/* ---------------------- Sorted gl_list_t Data Type ---------------------- */
664
665
static gl_list_node_t _GL_ATTRIBUTE_PURE
666
gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
667
                           const void *elt)
668
0
{
669
0
  for (gl_list_node_t node = list->root; node != NULL; )
670
0
    {
671
0
      int cmp = compar (node->value, elt);
672
673
0
      if (cmp < 0)
674
0
        node = node->right;
675
0
      else if (cmp > 0)
676
0
        node = node->left;
677
0
      else /* cmp == 0 */
678
0
        {
679
          /* We have an element equal to ELT.  But we need the leftmost such
680
             element.  */
681
0
          gl_list_node_t found = node;
682
0
          node = node->left;
683
0
          for (; node != NULL; )
684
0
            {
685
0
              int cmp2 = compar (node->value, elt);
686
687
0
              if (cmp2 < 0)
688
0
                node = node->right;
689
0
              else if (cmp2 > 0)
690
                /* The list was not sorted.  */
691
0
                abort ();
692
0
              else /* cmp2 == 0 */
693
0
                {
694
0
                  found = node;
695
0
                  node = node->left;
696
0
                }
697
0
            }
698
0
          return found;
699
0
        }
700
0
    }
701
0
  return NULL;
702
0
}
703
704
static gl_list_node_t _GL_ATTRIBUTE_PURE
705
gl_tree_sortedlist_search_from_to (gl_list_t list,
706
                                   gl_listelement_compar_fn compar,
707
                                   size_t low, size_t high,
708
                                   const void *elt)
709
0
{
710
0
  if (!(low <= high
711
0
        && high <= (list->root != NULL ? list->root->branch_size : 0)))
712
    /* Invalid arguments.  */
713
0
    abort ();
714
715
0
  for (gl_list_node_t node = list->root; node != NULL; )
716
0
    {
717
0
      size_t left_branch_size =
718
0
        (node->left != NULL ? node->left->branch_size : 0);
719
720
0
      if (low > left_branch_size)
721
0
        {
722
0
          low -= left_branch_size + 1;
723
0
          high -= left_branch_size + 1;
724
0
          node = node->right;
725
0
        }
726
0
      else if (high <= left_branch_size)
727
0
        node = node->left;
728
0
      else
729
0
        {
730
          /* Here low <= left_branch_size < high.  */
731
0
          int cmp = compar (node->value, elt);
732
733
0
          if (cmp < 0)
734
0
            {
735
0
              low = 0;
736
0
              high -= left_branch_size + 1;
737
0
              node = node->right;
738
0
            }
739
0
          else if (cmp > 0)
740
0
            node = node->left;
741
0
          else /* cmp == 0 */
742
0
            {
743
              /* We have an element equal to ELT.  But we need the leftmost
744
                 such element.  */
745
0
              gl_list_node_t found = node;
746
0
              node = node->left;
747
0
              for (; node != NULL; )
748
0
                {
749
0
                  size_t left_branch_size2 =
750
0
                    (node->left != NULL ? node->left->branch_size : 0);
751
752
0
                  if (low > left_branch_size2)
753
0
                    {
754
0
                      low -= left_branch_size2 + 1;
755
0
                      node = node->right;
756
0
                    }
757
0
                  else
758
0
                    {
759
                      /* Here low <= left_branch_size2.  */
760
0
                      int cmp2 = compar (node->value, elt);
761
762
0
                      if (cmp2 < 0)
763
0
                        {
764
0
                          low = 0;
765
0
                          node = node->right;
766
0
                        }
767
0
                      else if (cmp2 > 0)
768
                        /* The list was not sorted.  */
769
0
                        abort ();
770
0
                      else /* cmp2 == 0 */
771
0
                        {
772
0
                          found = node;
773
0
                          node = node->left;
774
0
                        }
775
0
                    }
776
0
                }
777
0
              return found;
778
0
            }
779
0
        }
780
0
    }
781
0
  return NULL;
782
0
}
783
784
static size_t _GL_ATTRIBUTE_PURE
785
gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
786
                            const void *elt)
787
0
{
788
0
  gl_list_node_t node;
789
0
  size_t position;
790
791
0
  for (node = list->root, position = 0; node != NULL; )
792
0
    {
793
0
      int cmp = compar (node->value, elt);
794
795
0
      if (cmp < 0)
796
0
        {
797
0
          if (node->left != NULL)
798
0
            position += node->left->branch_size;
799
0
          position++;
800
0
          node = node->right;
801
0
        }
802
0
      else if (cmp > 0)
803
0
        node = node->left;
804
0
      else /* cmp == 0 */
805
0
        {
806
          /* We have an element equal to ELT.  But we need the leftmost such
807
             element.  */
808
0
          size_t found_position =
809
0
            position + (node->left != NULL ? node->left->branch_size : 0);
810
0
          node = node->left;
811
0
          for (; node != NULL; )
812
0
            {
813
0
              int cmp2 = compar (node->value, elt);
814
815
0
              if (cmp2 < 0)
816
0
                {
817
0
                  if (node->left != NULL)
818
0
                    position += node->left->branch_size;
819
0
                  position++;
820
0
                  node = node->right;
821
0
                }
822
0
              else if (cmp2 > 0)
823
                /* The list was not sorted.  */
824
0
                abort ();
825
0
              else /* cmp2 == 0 */
826
0
                {
827
0
                  found_position =
828
0
                    position
829
0
                    + (node->left != NULL ? node->left->branch_size : 0);
830
0
                  node = node->left;
831
0
                }
832
0
            }
833
0
          return found_position;
834
0
        }
835
0
    }
836
0
  return (size_t)(-1);
837
0
}
838
839
static size_t _GL_ATTRIBUTE_PURE
840
gl_tree_sortedlist_indexof_from_to (gl_list_t list,
841
                                    gl_listelement_compar_fn compar,
842
                                    size_t low, size_t high,
843
                                    const void *elt)
844
0
{
845
0
  if (!(low <= high
846
0
        && high <= (list->root != NULL ? list->root->branch_size : 0)))
847
    /* Invalid arguments.  */
848
0
    abort ();
849
850
0
  gl_list_node_t node;
851
0
  size_t position;
852
853
0
  for (node = list->root, position = 0; node != NULL; )
854
0
    {
855
0
      size_t left_branch_size =
856
0
        (node->left != NULL ? node->left->branch_size : 0);
857
858
0
      if (low > left_branch_size)
859
0
        {
860
0
          low -= left_branch_size + 1;
861
0
          high -= left_branch_size + 1;
862
0
          position += left_branch_size + 1;
863
0
          node = node->right;
864
0
        }
865
0
      else if (high <= left_branch_size)
866
0
        node = node->left;
867
0
      else
868
0
        {
869
          /* Here low <= left_branch_size < high.  */
870
0
          int cmp = compar (node->value, elt);
871
872
0
          if (cmp < 0)
873
0
            {
874
0
              low = 0;
875
0
              high -= left_branch_size + 1;
876
0
              position += left_branch_size + 1;
877
0
              node = node->right;
878
0
            }
879
0
          else if (cmp > 0)
880
0
            node = node->left;
881
0
          else /* cmp == 0 */
882
0
            {
883
              /* We have an element equal to ELT.  But we need the leftmost
884
                 such element.  */
885
0
              size_t found_position =
886
0
                position + (node->left != NULL ? node->left->branch_size : 0);
887
0
              node = node->left;
888
0
              for (; node != NULL; )
889
0
                {
890
0
                  size_t left_branch_size2 =
891
0
                    (node->left != NULL ? node->left->branch_size : 0);
892
893
0
                  if (low > left_branch_size2)
894
0
                    {
895
0
                      low -= left_branch_size2 + 1;
896
0
                      node = node->right;
897
0
                    }
898
0
                  else
899
0
                    {
900
                      /* Here low <= left_branch_size2.  */
901
0
                      int cmp2 = compar (node->value, elt);
902
903
0
                      if (cmp2 < 0)
904
0
                        {
905
0
                          position += left_branch_size2 + 1;
906
0
                          node = node->right;
907
0
                        }
908
0
                      else if (cmp2 > 0)
909
                        /* The list was not sorted.  */
910
0
                        abort ();
911
0
                      else /* cmp2 == 0 */
912
0
                        {
913
0
                          found_position = position + left_branch_size2;
914
0
                          node = node->left;
915
0
                        }
916
0
                    }
917
0
                }
918
0
              return found_position;
919
0
            }
920
0
        }
921
0
    }
922
0
  return (size_t)(-1);
923
0
}
924
925
static gl_list_node_t
926
gl_tree_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
927
                           const void *elt)
928
0
{
929
0
  gl_list_node_t node = list->root;
930
931
0
  if (node == NULL)
932
0
    return gl_tree_nx_add_first (list, elt);
933
934
0
  for (;;)
935
0
    {
936
0
      int cmp = compar (node->value, elt);
937
938
0
      if (cmp < 0)
939
0
        {
940
0
          if (node->right == NULL)
941
0
            return gl_tree_nx_add_after (list, node, elt);
942
0
          node = node->right;
943
0
        }
944
0
      else if (cmp > 0)
945
0
        {
946
0
          if (node->left == NULL)
947
0
            return gl_tree_nx_add_before (list, node, elt);
948
0
          node = node->left;
949
0
        }
950
0
      else /* cmp == 0 */
951
0
        return gl_tree_nx_add_before (list, node, elt);
952
0
    }
953
0
}
954
955
static bool
956
gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
957
                           const void *elt)
958
0
{
959
0
  gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt);
960
0
  if (node != NULL)
961
0
    return gl_tree_remove_node (list, node);
962
0
  else
963
0
    return false;
964
0
}