(root)/
tar-1.35/
gnu/
malloc/
dynarray_emplace_enlarge.c
       1  /* Increase the size of a dynamic array in preparation of an emplace operation.
       2     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library 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 GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _LIBC
      20  # include <libc-config.h>
      21  #endif
      22  
      23  #include <dynarray.h>
      24  #include <errno.h>
      25  #include <stdckdint.h>
      26  #include <stdlib.h>
      27  #include <string.h>
      28  
      29  bool
      30  __libc_dynarray_emplace_enlarge (struct dynarray_header *list,
      31                                   void *scratch, size_t element_size)
      32  {
      33    size_t new_allocated;
      34    if (list->allocated == 0)
      35      {
      36        /* No scratch buffer provided.  Choose a reasonable default
      37           size.  */
      38        if (element_size < 4)
      39          new_allocated = 16;
      40        else if (element_size < 8)
      41          new_allocated = 8;
      42        else
      43          new_allocated = 4;
      44      }
      45    else
      46      /* Increase the allocated size, using an exponential growth
      47         policy.  */
      48      {
      49        new_allocated = list->allocated + list->allocated / 2 + 1;
      50        if (new_allocated <= list->allocated)
      51          {
      52            /* Overflow.  */
      53            __set_errno (ENOMEM);
      54            return false;
      55          }
      56      }
      57  
      58    size_t new_size;
      59    if (ckd_mul (&new_size, new_allocated, element_size))
      60      return false;
      61    void *new_array;
      62    if (list->array == scratch)
      63      {
      64        /* The previous array was not heap-allocated.  */
      65        new_array = malloc (new_size);
      66        if (new_array != NULL && list->array != NULL)
      67          memcpy (new_array, list->array, list->used * element_size);
      68      }
      69    else
      70      new_array = realloc (list->array, new_size);
      71    if (new_array == NULL)
      72      return false;
      73    list->array = new_array;
      74    list->allocated = new_allocated;
      75    return true;
      76  }
      77  libc_hidden_def (__libc_dynarray_emplace_enlarge)