root/maint/gnulib/lib/gl_carray_list.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gl_carray_nx_create_empty
  2. gl_carray_nx_create
  3. gl_carray_size
  4. gl_carray_node_value
  5. gl_carray_node_nx_set_value
  6. gl_carray_next_node
  7. gl_carray_previous_node
  8. gl_carray_first_node
  9. gl_carray_last_node
  10. gl_carray_get_at
  11. gl_carray_nx_set_at
  12. gl_carray_indexof_from_to
  13. gl_carray_search_from_to
  14. grow
  15. gl_carray_nx_add_first
  16. gl_carray_nx_add_last
  17. gl_carray_nx_add_at
  18. gl_carray_nx_add_before
  19. gl_carray_nx_add_after
  20. gl_carray_remove_at
  21. gl_carray_remove_node
  22. gl_carray_remove
  23. gl_carray_list_free
  24. gl_carray_iterator
  25. gl_carray_iterator_from_to
  26. gl_carray_iterator_next
  27. gl_carray_iterator_free
  28. gl_carray_sortedlist_indexof_from_to
  29. gl_carray_sortedlist_indexof
  30. gl_carray_sortedlist_search_from_to
  31. gl_carray_sortedlist_search
  32. gl_carray_sortedlist_nx_add
  33. gl_carray_sortedlist_remove

   1 /* Sequential list data type implemented by a circular array.
   2    Copyright (C) 2006-2021 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 #include <config.h>
  19 
  20 /* Specification.  */
  21 #include "gl_carray_list.h"
  22 
  23 #include <stdint.h>
  24 #include <stdlib.h>
  25 /* Get memcpy.  */
  26 #include <string.h>
  27 
  28 /* Checked size_t computations.  */
  29 #include "xsize.h"
  30 
  31 /* -------------------------- gl_list_t Data Type -------------------------- */
  32 
  33 /* Concrete gl_list_impl type, valid for this file only.  */
  34 struct gl_list_impl
  35 {
  36   struct gl_list_impl_base base;
  37   /* An array of ALLOCATED elements, of which the elements
  38      OFFSET, (OFFSET + 1) % ALLOCATED, ..., (OFFSET + COUNT - 1) % ALLOCATED
  39      are used.  0 <= COUNT <= ALLOCATED.  Either OFFSET = ALLOCATED = 0 or
  40      0 <= OFFSET < ALLOCATED.  */
  41   const void **elements;
  42   size_t offset;
  43   size_t count;
  44   size_t allocated;
  45 };
  46 
  47 /* struct gl_list_node_impl doesn't exist here.  The pointers are actually
  48    indices + 1.  */
  49 #define INDEX_TO_NODE(index) (gl_list_node_t)(uintptr_t)(size_t)((index) + 1)
  50 #define NODE_TO_INDEX(node) ((uintptr_t)(node) - 1)
  51 
  52 static gl_list_t
  53 gl_carray_nx_create_empty (gl_list_implementation_t implementation,
     /* [previous][next][first][last][top][bottom][index][help] */
  54                            gl_listelement_equals_fn equals_fn,
  55                            gl_listelement_hashcode_fn hashcode_fn,
  56                            gl_listelement_dispose_fn dispose_fn,
  57                            bool allow_duplicates)
  58 {
  59   struct gl_list_impl *list =
  60     (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
  61 
  62   if (list == NULL)
  63     return NULL;
  64 
  65   list->base.vtable = implementation;
  66   list->base.equals_fn = equals_fn;
  67   list->base.hashcode_fn = hashcode_fn;
  68   list->base.dispose_fn = dispose_fn;
  69   list->base.allow_duplicates = allow_duplicates;
  70   list->elements = NULL;
  71   list->offset = 0;
  72   list->count = 0;
  73   list->allocated = 0;
  74 
  75   return list;
  76 }
  77 
  78 static gl_list_t
  79 gl_carray_nx_create (gl_list_implementation_t implementation,
     /* [previous][next][first][last][top][bottom][index][help] */
  80                   gl_listelement_equals_fn equals_fn,
  81                   gl_listelement_hashcode_fn hashcode_fn,
  82                   gl_listelement_dispose_fn dispose_fn,
  83                   bool allow_duplicates,
  84                   size_t count, const void **contents)
  85 {
  86   struct gl_list_impl *list =
  87     (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
  88 
  89   if (list == NULL)
  90     return NULL;
  91 
  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;
  97   if (count > 0)
  98     {
  99       if (size_overflow_p (xtimes (count, sizeof (const void *))))
 100         goto fail;
 101       list->elements = (const void **) malloc (count * sizeof (const void *));
 102       if (list->elements == NULL)
 103         goto fail;
 104       memcpy (list->elements, contents, count * sizeof (const void *));
 105     }
 106   else
 107     list->elements = NULL;
 108   list->offset = 0;
 109   list->count = count;
 110   list->allocated = count;
 111 
 112   return list;
 113 
 114  fail:
 115   free (list);
 116   return NULL;
 117 }
 118 
 119 static size_t _GL_ATTRIBUTE_PURE
 120 gl_carray_size (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122   return list->count;
 123 }
 124 
 125 static const void * _GL_ATTRIBUTE_PURE
 126 gl_carray_node_value (gl_list_t list, gl_list_node_t node)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128   uintptr_t index = NODE_TO_INDEX (node);
 129   size_t i;
 130 
 131   if (!(index < list->count))
 132     /* Invalid argument.  */
 133     abort ();
 134   i = list->offset + index;
 135   if (i >= list->allocated)
 136     i -= list->allocated;
 137   return list->elements[i];
 138 }
 139 
 140 static int
 141 gl_carray_node_nx_set_value (gl_list_t list, gl_list_node_t node,
     /* [previous][next][first][last][top][bottom][index][help] */
 142                              const void *elt)
 143 {
 144   uintptr_t index = NODE_TO_INDEX (node);
 145   size_t i;
 146 
 147   if (!(index < list->count))
 148     /* Invalid argument.  */
 149     abort ();
 150   i = list->offset + index;
 151   if (i >= list->allocated)
 152     i -= list->allocated;
 153   list->elements[i] = elt;
 154   return 0;
 155 }
 156 
 157 static gl_list_node_t _GL_ATTRIBUTE_PURE
 158 gl_carray_next_node (gl_list_t list, gl_list_node_t node)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160   uintptr_t index = NODE_TO_INDEX (node);
 161   if (!(index < list->count))
 162     /* Invalid argument.  */
 163     abort ();
 164   index++;
 165   if (index < list->count)
 166     return INDEX_TO_NODE (index);
 167   else
 168     return NULL;
 169 }
 170 
 171 static gl_list_node_t _GL_ATTRIBUTE_PURE
 172 gl_carray_previous_node (gl_list_t list, gl_list_node_t node)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174   uintptr_t index = NODE_TO_INDEX (node);
 175   if (!(index < list->count))
 176     /* Invalid argument.  */
 177     abort ();
 178   if (index > 0)
 179     return INDEX_TO_NODE (index - 1);
 180   else
 181     return NULL;
 182 }
 183 
 184 static gl_list_node_t _GL_ATTRIBUTE_PURE
 185 gl_carray_first_node (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187   if (list->count > 0)
 188     return INDEX_TO_NODE (0);
 189   else
 190     return NULL;
 191 }
 192 
 193 static gl_list_node_t _GL_ATTRIBUTE_PURE
 194 gl_carray_last_node (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196   if (list->count > 0)
 197     return INDEX_TO_NODE (list->count - 1);
 198   else
 199     return NULL;
 200 }
 201 
 202 static const void * _GL_ATTRIBUTE_PURE
 203 gl_carray_get_at (gl_list_t list, size_t position)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205   size_t count = list->count;
 206   size_t i;
 207 
 208   if (!(position < count))
 209     /* Invalid argument.  */
 210     abort ();
 211   i = list->offset + position;
 212   if (i >= list->allocated)
 213     i -= list->allocated;
 214   return list->elements[i];
 215 }
 216 
 217 static gl_list_node_t
 218 gl_carray_nx_set_at (gl_list_t list, size_t position, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220   size_t count = list->count;
 221   size_t i;
 222 
 223   if (!(position < count))
 224     /* Invalid argument.  */
 225     abort ();
 226   i = list->offset + position;
 227   if (i >= list->allocated)
 228     i -= list->allocated;
 229   list->elements[i] = elt;
 230   return INDEX_TO_NODE (position);
 231 }
 232 
 233 static size_t _GL_ATTRIBUTE_PURE
 234 gl_carray_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
     /* [previous][next][first][last][top][bottom][index][help] */
 235                            const void *elt)
 236 {
 237   size_t count = list->count;
 238 
 239   if (!(start_index <= end_index && end_index <= count))
 240     /* Invalid arguments.  */
 241     abort ();
 242 
 243   if (start_index < end_index)
 244     {
 245       gl_listelement_equals_fn equals = list->base.equals_fn;
 246       size_t allocated = list->allocated;
 247       size_t i_end;
 248 
 249       i_end = list->offset + end_index;
 250       if (i_end >= allocated)
 251         i_end -= allocated;
 252 
 253       if (equals != NULL)
 254         {
 255           size_t i;
 256 
 257           i = list->offset + start_index;
 258           if (i >= allocated) /* can only happen if start_index > 0 */
 259             i -= allocated;
 260 
 261           for (;;)
 262             {
 263               if (equals (elt, list->elements[i]))
 264                 return (i >= list->offset ? i : i + allocated) - list->offset;
 265               i++;
 266               if (i == allocated)
 267                 i = 0;
 268               if (i == i_end)
 269                 break;
 270             }
 271         }
 272       else
 273         {
 274           size_t i;
 275 
 276           i = list->offset + start_index;
 277           if (i >= allocated) /* can only happen if start_index > 0 */
 278             i -= allocated;
 279 
 280           for (;;)
 281             {
 282               if (elt == list->elements[i])
 283                 return (i >= list->offset ? i : i + allocated) - list->offset;
 284               i++;
 285               if (i == allocated)
 286                 i = 0;
 287               if (i == i_end)
 288                 break;
 289             }
 290         }
 291     }
 292   return (size_t)(-1);
 293 }
 294 
 295 static gl_list_node_t _GL_ATTRIBUTE_PURE
 296 gl_carray_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
     /* [previous][next][first][last][top][bottom][index][help] */
 297                           const void *elt)
 298 {
 299   size_t index = gl_carray_indexof_from_to (list, start_index, end_index, elt);
 300   return INDEX_TO_NODE (index);
 301 }
 302 
 303 /* Ensure that list->allocated > list->count.
 304    Return 0 upon success, -1 upon out-of-memory.  */
 305 static int
 306 grow (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308   size_t new_allocated;
 309   size_t memory_size;
 310   const void **memory;
 311 
 312   new_allocated = xtimes (list->allocated, 2);
 313   new_allocated = xsum (new_allocated, 1);
 314   memory_size = xtimes (new_allocated, sizeof (const void *));
 315   if (size_overflow_p (memory_size))
 316     /* Overflow, would lead to out of memory.  */
 317     return -1;
 318   if (list->offset > 0 && list->count > 0)
 319     {
 320       memory = (const void **) malloc (memory_size);
 321       if (memory == NULL)
 322         /* Out of memory.  */
 323         return -1;
 324       if (list->offset + list->count > list->allocated)
 325         {
 326           memcpy (memory, &list->elements[list->offset],
 327                   (list->allocated - list->offset) * sizeof (const void *));
 328           memcpy (memory + (list->allocated - list->offset), list->elements,
 329                   (list->offset + list->count - list->allocated)
 330                   * sizeof (const void *));
 331 
 332         }
 333       else
 334         memcpy (memory, &list->elements[list->offset],
 335                 list->count * sizeof (const void *));
 336       if (list->elements != NULL)
 337         free (list->elements);
 338     }
 339   else
 340     {
 341       memory = (const void **) realloc (list->elements, memory_size);
 342       if (memory == NULL)
 343         /* Out of memory.  */
 344         return -1;
 345     }
 346   list->elements = memory;
 347   list->offset = 0;
 348   list->allocated = new_allocated;
 349   return 0;
 350 }
 351 
 352 static gl_list_node_t
 353 gl_carray_nx_add_first (gl_list_t list, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 354 {
 355   size_t count = list->count;
 356 
 357   if (count == list->allocated)
 358     if (grow (list) < 0)
 359       return NULL;
 360   list->offset = (list->offset == 0 ? list->allocated : list->offset) - 1;
 361   list->elements[list->offset] = elt;
 362   list->count = count + 1;
 363   return INDEX_TO_NODE (0);
 364 }
 365 
 366 static gl_list_node_t
 367 gl_carray_nx_add_last (gl_list_t list, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369   size_t count = list->count;
 370   size_t i;
 371 
 372   if (count == list->allocated)
 373     if (grow (list) < 0)
 374       return NULL;
 375   i = list->offset + count;
 376   if (i >= list->allocated)
 377     i -= list->allocated;
 378   list->elements[i] = elt;
 379   list->count = count + 1;
 380   return INDEX_TO_NODE (count);
 381 }
 382 
 383 static gl_list_node_t
 384 gl_carray_nx_add_at (gl_list_t list, size_t position, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386   size_t count = list->count;
 387   const void **elements;
 388 
 389   if (!(position <= count))
 390     /* Invalid argument.  */
 391     abort ();
 392   if (count == list->allocated)
 393     if (grow (list) < 0)
 394       return NULL;
 395   elements = list->elements;
 396   if (position <= (count / 2))
 397     {
 398       /* Shift at most count/2 elements to the left.  */
 399       size_t i2, i;
 400 
 401       list->offset = (list->offset == 0 ? list->allocated : list->offset) - 1;
 402 
 403       i2 = list->offset + position;
 404       if (i2 >= list->allocated)
 405         {
 406           /* Here we must have list->offset > 0, hence list->allocated > 0.  */
 407           size_t i1 = list->allocated - 1;
 408           i2 -= list->allocated;
 409           for (i = list->offset; i < i1; i++)
 410             elements[i] = elements[i + 1];
 411           elements[i1] = elements[0];
 412           for (i = 0; i < i2; i++)
 413             elements[i] = elements[i + 1];
 414         }
 415       else
 416         {
 417           for (i = list->offset; i < i2; i++)
 418             elements[i] = elements[i + 1];
 419         }
 420       elements[i2] = elt;
 421     }
 422   else
 423     {
 424       /* Shift at most (count+1)/2 elements to the right.  */
 425       size_t i1, i3, i;
 426 
 427       i1 = list->offset + position;
 428       i3 = list->offset + count;
 429       if (i1 >= list->allocated)
 430         {
 431           i1 -= list->allocated;
 432           i3 -= list->allocated;
 433           for (i = i3; i > i1; i--)
 434             elements[i] = elements[i - 1];
 435         }
 436       else if (i3 >= list->allocated)
 437         {
 438           /* Here we must have list->offset > 0, hence list->allocated > 0.  */
 439           size_t i2 = list->allocated - 1;
 440           i3 -= list->allocated;
 441           for (i = i3; i > 0; i--)
 442             elements[i] = elements[i - 1];
 443           elements[0] = elements[i2];
 444           for (i = i2; i > i1; i--)
 445             elements[i] = elements[i - 1];
 446         }
 447       else
 448         {
 449           for (i = i3; i > i1; i--)
 450             elements[i] = elements[i - 1];
 451         }
 452       elements[i1] = elt;
 453     }
 454   list->count = count + 1;
 455   return INDEX_TO_NODE (position);
 456 }
 457 
 458 static gl_list_node_t
 459 gl_carray_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461   size_t count = list->count;
 462   uintptr_t index = NODE_TO_INDEX (node);
 463 
 464   if (!(index < count))
 465     /* Invalid argument.  */
 466     abort ();
 467   return gl_carray_nx_add_at (list, index, elt);
 468 }
 469 
 470 static gl_list_node_t
 471 gl_carray_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 472 {
 473   size_t count = list->count;
 474   uintptr_t index = NODE_TO_INDEX (node);
 475 
 476   if (!(index < count))
 477     /* Invalid argument.  */
 478     abort ();
 479   return gl_carray_nx_add_at (list, index + 1, elt);
 480 }
 481 
 482 static bool
 483 gl_carray_remove_at (gl_list_t list, size_t position)
     /* [previous][next][first][last][top][bottom][index][help] */
 484 {
 485   size_t count = list->count;
 486   const void **elements;
 487 
 488   if (!(position < count))
 489     /* Invalid argument.  */
 490     abort ();
 491   /* Here we know count > 0.  */
 492   elements = list->elements;
 493   if (position <= ((count - 1) / 2))
 494     {
 495       /* Shift at most (count-1)/2 elements to the right.  */
 496       size_t i0, i2, i;
 497 
 498       i0 = list->offset;
 499       i2 = list->offset + position;
 500       if (i2 >= list->allocated)
 501         {
 502           /* Here we must have list->offset > 0, hence list->allocated > 0.  */
 503           size_t i1 = list->allocated - 1;
 504           i2 -= list->allocated;
 505           if (list->base.dispose_fn != NULL)
 506             list->base.dispose_fn (elements[i2]);
 507           for (i = i2; i > 0; i--)
 508             elements[i] = elements[i - 1];
 509           elements[0] = elements[i1];
 510           for (i = i1; i > i0; i--)
 511             elements[i] = elements[i - 1];
 512         }
 513       else
 514         {
 515           if (list->base.dispose_fn != NULL)
 516             list->base.dispose_fn (elements[i2]);
 517           for (i = i2; i > i0; i--)
 518             elements[i] = elements[i - 1];
 519         }
 520 
 521       i0++;
 522       list->offset = (i0 == list->allocated ? 0 : i0);
 523     }
 524   else
 525     {
 526       /* Shift at most count/2 elements to the left.  */
 527       size_t i1, i3, i;
 528 
 529       i1 = list->offset + position;
 530       i3 = list->offset + count - 1;
 531       if (i1 >= list->allocated)
 532         {
 533           i1 -= list->allocated;
 534           i3 -= list->allocated;
 535           if (list->base.dispose_fn != NULL)
 536             list->base.dispose_fn (elements[i1]);
 537           for (i = i1; i < i3; i++)
 538             elements[i] = elements[i + 1];
 539         }
 540       else if (i3 >= list->allocated)
 541         {
 542           /* Here we must have list->offset > 0, hence list->allocated > 0.  */
 543           size_t i2 = list->allocated - 1;
 544           i3 -= list->allocated;
 545           if (list->base.dispose_fn != NULL)
 546             list->base.dispose_fn (elements[i1]);
 547           for (i = i1; i < i2; i++)
 548             elements[i] = elements[i + 1];
 549           elements[i2] = elements[0];
 550           for (i = 0; i < i3; i++)
 551             elements[i] = elements[i + 1];
 552         }
 553       else
 554         {
 555           if (list->base.dispose_fn != NULL)
 556             list->base.dispose_fn (elements[i1]);
 557           for (i = i1; i < i3; i++)
 558             elements[i] = elements[i + 1];
 559         }
 560     }
 561   list->count = count - 1;
 562   return true;
 563 }
 564 
 565 static bool
 566 gl_carray_remove_node (gl_list_t list, gl_list_node_t node)
     /* [previous][next][first][last][top][bottom][index][help] */
 567 {
 568   size_t count = list->count;
 569   uintptr_t index = NODE_TO_INDEX (node);
 570 
 571   if (!(index < count))
 572     /* Invalid argument.  */
 573     abort ();
 574   return gl_carray_remove_at (list, index);
 575 }
 576 
 577 static bool
 578 gl_carray_remove (gl_list_t list, const void *elt)
     /* [previous][next][first][last][top][bottom][index][help] */
 579 {
 580   size_t position = gl_carray_indexof_from_to (list, 0, list->count, elt);
 581   if (position == (size_t)(-1))
 582     return false;
 583   else
 584     return gl_carray_remove_at (list, position);
 585 }
 586 
 587 static void
 588 gl_carray_list_free (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 589 {
 590   if (list->elements != NULL)
 591     {
 592       if (list->base.dispose_fn != NULL)
 593         {
 594           size_t count = list->count;
 595 
 596           if (count > 0)
 597             {
 598               gl_listelement_dispose_fn dispose = list->base.dispose_fn;
 599               const void **elements = list->elements;
 600               size_t i1 = list->offset;
 601               size_t i3 = list->offset + count - 1;
 602 
 603               if (i3 >= list->allocated)
 604                 {
 605                   /* Here we must have list->offset > 0, hence
 606                      list->allocated > 0.  */
 607                   size_t i2 = list->allocated - 1;
 608                   size_t i;
 609 
 610                   i3 -= list->allocated;
 611                   for (i = i1; i <= i2; i++)
 612                     dispose (elements[i]);
 613                   for (i = 0; i <= i3; i++)
 614                     dispose (elements[i]);
 615                 }
 616               else
 617                 {
 618                   size_t i;
 619 
 620                   for (i = i1; i <= i3; i++)
 621                     dispose (elements[i]);
 622                 }
 623             }
 624         }
 625       free (list->elements);
 626     }
 627   free (list);
 628 }
 629 
 630 /* --------------------- gl_list_iterator_t Data Type --------------------- */
 631 
 632 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
 633 gl_carray_iterator (gl_list_t list)
     /* [previous][next][first][last][top][bottom][index][help] */
 634 {
 635   gl_list_iterator_t result;
 636 
 637   result.vtable = list->base.vtable;
 638   result.list = list;
 639   result.count = list->count;
 640   result.i = 0;
 641   result.j = list->count;
 642 #if defined GCC_LINT || defined lint
 643   result.p = 0;
 644   result.q = 0;
 645 #endif
 646 
 647   return result;
 648 }
 649 
 650 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
 651 gl_carray_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653   gl_list_iterator_t result;
 654 
 655   if (!(start_index <= end_index && end_index <= list->count))
 656     /* Invalid arguments.  */
 657     abort ();
 658   result.vtable = list->base.vtable;
 659   result.list = list;
 660   result.count = list->count;
 661   result.i = start_index;
 662   result.j = end_index;
 663 #if defined GCC_LINT || defined lint
 664   result.p = 0;
 665   result.q = 0;
 666 #endif
 667 
 668   return result;
 669 }
 670 
 671 static bool
 672 gl_carray_iterator_next (gl_list_iterator_t *iterator,
     /* [previous][next][first][last][top][bottom][index][help] */
 673                          const void **eltp, gl_list_node_t *nodep)
 674 {
 675   gl_list_t list = iterator->list;
 676   if (iterator->count != list->count)
 677     {
 678       if (iterator->count != list->count + 1)
 679         /* Concurrent modifications were done on the list.  */
 680         abort ();
 681       /* The last returned element was removed.  */
 682       iterator->count--;
 683       iterator->i--;
 684       iterator->j--;
 685     }
 686   if (iterator->i < iterator->j)
 687     {
 688       size_t i = list->offset + iterator->i;
 689       if (i >= list->allocated)
 690         i -= list->allocated;
 691       *eltp = list->elements[i];
 692       if (nodep != NULL)
 693         *nodep = INDEX_TO_NODE (iterator->i);
 694       iterator->i++;
 695       return true;
 696     }
 697   else
 698     return false;
 699 }
 700 
 701 static void
 702 gl_carray_iterator_free (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_iterator_t *iterator)
     /* [previous][next][first][last][top][bottom][index][help] */
 703 {
 704 }
 705 
 706 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
 707 
 708 static size_t _GL_ATTRIBUTE_PURE
 709 gl_carray_sortedlist_indexof_from_to (gl_list_t list,
     /* [previous][next][first][last][top][bottom][index][help] */
 710                                       gl_listelement_compar_fn compar,
 711                                       size_t low, size_t high,
 712                                       const void *elt)
 713 {
 714   if (!(low <= high && high <= list->count))
 715     /* Invalid arguments.  */
 716     abort ();
 717   if (low < high)
 718     {
 719       /* At each loop iteration, low < high; for indices < low the values
 720          are smaller than ELT; for indices >= high the values are greater
 721          than ELT.  So, if the element occurs in the list, it is at
 722          low <= position < high.  */
 723       do
 724         {
 725           size_t mid = low + (high - low) / 2; /* low <= mid < high */
 726           size_t i_mid;
 727           int cmp;
 728 
 729           i_mid = list->offset + mid;
 730           if (i_mid >= list->allocated)
 731             i_mid -= list->allocated;
 732 
 733           cmp = compar (list->elements[i_mid], elt);
 734 
 735           if (cmp < 0)
 736             low = mid + 1;
 737           else if (cmp > 0)
 738             high = mid;
 739           else /* cmp == 0 */
 740             {
 741               /* We have an element equal to ELT at index MID.  But we need
 742                  the minimal such index.  */
 743               high = mid;
 744               /* At each loop iteration, low <= high and
 745                    compar (list->elements[i_high], elt) == 0,
 746                  and we know that the first occurrence of the element is at
 747                  low <= position <= high.  */
 748               while (low < high)
 749                 {
 750                   size_t mid2 = low + (high - low) / 2; /* low <= mid2 < high */
 751                   size_t i_mid2;
 752                   int cmp2;
 753 
 754                   i_mid2 = list->offset + mid2;
 755                   if (i_mid2 >= list->allocated)
 756                     i_mid2 -= list->allocated;
 757 
 758                   cmp2 = compar (list->elements[i_mid2], elt);
 759 
 760                   if (cmp2 < 0)
 761                     low = mid2 + 1;
 762                   else if (cmp2 > 0)
 763                     /* The list was not sorted.  */
 764                     abort ();
 765                   else /* cmp2 == 0 */
 766                     {
 767                       if (mid2 == low)
 768                         break;
 769                       high = mid2 - 1;
 770                     }
 771                 }
 772               return low;
 773             }
 774         }
 775       while (low < high);
 776       /* Here low == high.  */
 777     }
 778   return (size_t)(-1);
 779 }
 780 
 781 static size_t _GL_ATTRIBUTE_PURE
 782 gl_carray_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
     /* [previous][next][first][last][top][bottom][index][help] */
 783                               const void *elt)
 784 {
 785   return gl_carray_sortedlist_indexof_from_to (list, compar, 0, list->count,
 786                                                elt);
 787 }
 788 
 789 static gl_list_node_t _GL_ATTRIBUTE_PURE
 790 gl_carray_sortedlist_search_from_to (gl_list_t list,
     /* [previous][next][first][last][top][bottom][index][help] */
 791                                      gl_listelement_compar_fn compar,
 792                                      size_t low, size_t high,
 793                                      const void *elt)
 794 {
 795   size_t index =
 796     gl_carray_sortedlist_indexof_from_to (list, compar, low, high, elt);
 797   return INDEX_TO_NODE (index);
 798 }
 799 
 800 static gl_list_node_t _GL_ATTRIBUTE_PURE
 801 gl_carray_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
     /* [previous][next][first][last][top][bottom][index][help] */
 802                              const void *elt)
 803 {
 804   size_t index =
 805     gl_carray_sortedlist_indexof_from_to (list, compar, 0, list->count, elt);
 806   return INDEX_TO_NODE (index);
 807 }
 808 
 809 static gl_list_node_t
 810 gl_carray_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
     /* [previous][next][first][last][top][bottom][index][help] */
 811                              const void *elt)
 812 {
 813   size_t count = list->count;
 814   size_t low = 0;
 815   size_t high = count;
 816 
 817   /* At each loop iteration, low <= high; for indices < low the values are
 818      smaller than ELT; for indices >= high the values are greater than ELT.  */
 819   while (low < high)
 820     {
 821       size_t mid = low + (high - low) / 2; /* low <= mid < high */
 822       size_t i_mid;
 823       int cmp;
 824 
 825       i_mid = list->offset + mid;
 826       if (i_mid >= list->allocated)
 827         i_mid -= list->allocated;
 828 
 829       cmp = compar (list->elements[i_mid], elt);
 830 
 831       if (cmp < 0)
 832         low = mid + 1;
 833       else if (cmp > 0)
 834         high = mid;
 835       else /* cmp == 0 */
 836         {
 837           low = mid;
 838           break;
 839         }
 840     }
 841   return gl_carray_nx_add_at (list, low, elt);
 842 }
 843 
 844 static bool
 845 gl_carray_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
     /* [previous][next][first][last][top][bottom][index][help] */
 846                              const void *elt)
 847 {
 848   size_t index = gl_carray_sortedlist_indexof (list, compar, elt);
 849   if (index == (size_t)(-1))
 850     return false;
 851   else
 852     return gl_carray_remove_at (list, index);
 853 }
 854 
 855 
 856 const struct gl_list_implementation gl_carray_list_implementation =
 857   {
 858     gl_carray_nx_create_empty,
 859     gl_carray_nx_create,
 860     gl_carray_size,
 861     gl_carray_node_value,
 862     gl_carray_node_nx_set_value,
 863     gl_carray_next_node,
 864     gl_carray_previous_node,
 865     gl_carray_first_node,
 866     gl_carray_last_node,
 867     gl_carray_get_at,
 868     gl_carray_nx_set_at,
 869     gl_carray_search_from_to,
 870     gl_carray_indexof_from_to,
 871     gl_carray_nx_add_first,
 872     gl_carray_nx_add_last,
 873     gl_carray_nx_add_before,
 874     gl_carray_nx_add_after,
 875     gl_carray_nx_add_at,
 876     gl_carray_remove_node,
 877     gl_carray_remove_at,
 878     gl_carray_remove,
 879     gl_carray_list_free,
 880     gl_carray_iterator,
 881     gl_carray_iterator_from_to,
 882     gl_carray_iterator_next,
 883     gl_carray_iterator_free,
 884     gl_carray_sortedlist_search,
 885     gl_carray_sortedlist_search_from_to,
 886     gl_carray_sortedlist_indexof,
 887     gl_carray_sortedlist_indexof_from_to,
 888     gl_carray_sortedlist_nx_add,
 889     gl_carray_sortedlist_remove
 890   };

/* [previous][next][first][last][top][bottom][index][help] */