Coverage Report

Created: 2026-11-12 07:51

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