Blame malloc/dynarray.h

Packit Service 82fcde
/* Type-safe arrays which grow dynamically.  Shared definitions.
Packit Service 82fcde
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* To use the dynarray facility, you need to include
Packit Service 82fcde
   <malloc/dynarray-skeleton.c> and define the parameter macros
Packit Service 82fcde
   documented in that file.
Packit Service 82fcde
Packit Service 82fcde
   A minimal example which provides a growing list of integers can be
Packit Service 82fcde
   defined like this:
Packit Service 82fcde
Packit Service 82fcde
     struct int_array
Packit Service 82fcde
     {
Packit Service 82fcde
       // Pointer to result array followed by its length,
Packit Service 82fcde
       // as required by DYNARRAY_FINAL_TYPE.
Packit Service 82fcde
       int *array;
Packit Service 82fcde
       size_t length;
Packit Service 82fcde
     };
Packit Service 82fcde
Packit Service 82fcde
     #define DYNARRAY_STRUCT dynarray_int
Packit Service 82fcde
     #define DYNARRAY_ELEMENT int
Packit Service 82fcde
     #define DYNARRAY_PREFIX dynarray_int_
Packit Service 82fcde
     #define DYNARRAY_FINAL_TYPE struct int_array
Packit Service 82fcde
     #include <malloc/dynarray-skeleton.c>
Packit Service 82fcde
Packit Service 82fcde
   To create a three-element array with elements 1, 2, 3, use this
Packit Service 82fcde
   code:
Packit Service 82fcde
Packit Service 82fcde
     struct dynarray_int dyn;
Packit Service 82fcde
     dynarray_int_init (&dyn);
Packit Service 82fcde
     for (int i = 1; i <= 3; ++i)
Packit Service 82fcde
       {
Packit Service 82fcde
         int *place = dynarray_int_emplace (&dyn);
Packit Service 82fcde
         assert (place != NULL);
Packit Service 82fcde
         *place = i;
Packit Service 82fcde
       }
Packit Service 82fcde
     struct int_array result;
Packit Service 82fcde
     bool ok = dynarray_int_finalize (&dyn, &result);
Packit Service 82fcde
     assert (ok);
Packit Service 82fcde
     assert (result.length == 3);
Packit Service 82fcde
     assert (result.array[0] == 1);
Packit Service 82fcde
     assert (result.array[1] == 2);
Packit Service 82fcde
     assert (result.array[2] == 3);
Packit Service 82fcde
     free (result.array);
Packit Service 82fcde
Packit Service 82fcde
   If the elements contain resources which must be freed, define
Packit Service 82fcde
   DYNARRAY_ELEMENT_FREE appropriately, like this:
Packit Service 82fcde
Packit Service 82fcde
     struct str_array
Packit Service 82fcde
     {
Packit Service 82fcde
       char **array;
Packit Service 82fcde
       size_t length;
Packit Service 82fcde
     };
Packit Service 82fcde
Packit Service 82fcde
     #define DYNARRAY_STRUCT dynarray_str
Packit Service 82fcde
     #define DYNARRAY_ELEMENT char *
Packit Service 82fcde
     #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
Packit Service 82fcde
     #define DYNARRAY_PREFIX dynarray_str_
Packit Service 82fcde
     #define DYNARRAY_FINAL_TYPE struct str_array
Packit Service 82fcde
     #include <malloc/dynarray-skeleton.c>
Packit Service 82fcde
Packit Service 82fcde
   Compared to scratch buffers, dynamic arrays have the following
Packit Service 82fcde
   features:
Packit Service 82fcde
Packit Service 82fcde
   - They have an element type, and are not just an untyped buffer of
Packit Service 82fcde
     bytes.
Packit Service 82fcde
Packit Service 82fcde
   - When growing, previously stored elements are preserved.  (It is
Packit Service 82fcde
     expected that scratch_buffer_grow_preserve and
Packit Service 82fcde
     scratch_buffer_set_array_size eventually go away because all
Packit Service 82fcde
     current users are moved to dynamic arrays.)
Packit Service 82fcde
Packit Service 82fcde
   - Scratch buffers have a more aggressive growth policy because
Packit Service 82fcde
     growing them typically means a retry of an operation (across an
Packit Service 82fcde
     NSS service module boundary), which is expensive.
Packit Service 82fcde
Packit Service 82fcde
   - For the same reason, scratch buffers have a much larger initial
Packit Service 82fcde
     stack allocation.  */
Packit Service 82fcde
Packit Service 82fcde
#ifndef _DYNARRAY_H
Packit Service 82fcde
#define _DYNARRAY_H
Packit Service 82fcde
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stddef.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
struct dynarray_header
Packit Service 82fcde
{
Packit Service 82fcde
  size_t used;
Packit Service 82fcde
  size_t allocated;
Packit Service 82fcde
  void *array;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Marker used in the allocated member to indicate that an error was
Packit Service 82fcde
   encountered.  */
Packit Service 82fcde
static inline size_t
Packit Service 82fcde
__dynarray_error_marker (void)
Packit Service 82fcde
{
Packit Service 82fcde
  return -1;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  See the has_failed function in
Packit Service 82fcde
   dynarray-skeleton.c.  */
Packit Service 82fcde
static inline bool
Packit Service 82fcde
__dynarray_error (struct dynarray_header *list)
Packit Service 82fcde
{
Packit Service 82fcde
  return list->allocated == __dynarray_error_marker ();
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  Enlarge the dynamically allocated area of the
Packit Service 82fcde
   array to make room for one more element.  SCRATCH is a pointer to
Packit Service 82fcde
   the scratch area (which is not heap-allocated and must not be
Packit Service 82fcde
   freed).  ELEMENT_SIZE is the size, in bytes, of one element.
Packit Service 82fcde
   Return false on failure, true on success.  */
Packit Service 82fcde
bool __libc_dynarray_emplace_enlarge (struct dynarray_header *,
Packit Service 82fcde
                                      void *scratch, size_t element_size);
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  Enlarge the dynamically allocated area of the
Packit Service 82fcde
   array to make room for at least SIZE elements (which must be larger
Packit Service 82fcde
   than the existing used part of the dynamic array).  SCRATCH is a
Packit Service 82fcde
   pointer to the scratch area (which is not heap-allocated and must
Packit Service 82fcde
   not be freed).  ELEMENT_SIZE is the size, in bytes, of one element.
Packit Service 82fcde
   Return false on failure, true on success.  */
Packit Service 82fcde
bool __libc_dynarray_resize (struct dynarray_header *, size_t size,
Packit Service 82fcde
                             void *scratch, size_t element_size);
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  Like __libc_dynarray_resize, but clear the new
Packit Service 82fcde
   part of the dynamic array.  */
Packit Service 82fcde
bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size,
Packit Service 82fcde
                                   void *scratch, size_t element_size);
Packit Service 82fcde
Packit Service 82fcde
/* Internal type.  */
Packit Service 82fcde
struct dynarray_finalize_result
Packit Service 82fcde
{
Packit Service 82fcde
  void *array;
Packit Service 82fcde
  size_t length;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  Copy the dynamically-allocated area to an
Packit Service 82fcde
   explicitly-sized heap allocation.  SCRATCH is a pointer to the
Packit Service 82fcde
   embedded scratch space.  ELEMENT_SIZE is the size, in bytes, of the
Packit Service 82fcde
   element type.  On success, true is returned, and pointer and length
Packit Service 82fcde
   are written to *RESULT.  On failure, false is returned.  The caller
Packit Service 82fcde
   has to take care of some of the memory management; this function is
Packit Service 82fcde
   expected to be called from dynarray-skeleton.c.  */
Packit Service 82fcde
bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
Packit Service 82fcde
                               size_t element_size,
Packit Service 82fcde
                               struct dynarray_finalize_result *result);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Internal function.  Terminate the process after an index error.
Packit Service 82fcde
   SIZE is the number of elements of the dynamic array.  INDEX is the
Packit Service 82fcde
   lookup index which triggered the failure.  */
Packit Service 82fcde
void __libc_dynarray_at_failure (size_t size, size_t index)
Packit Service 82fcde
  __attribute__ ((noreturn));
Packit Service 82fcde
Packit Service 82fcde
#ifndef _ISOMAC
Packit Service 82fcde
libc_hidden_proto (__libc_dynarray_emplace_enlarge)
Packit Service 82fcde
libc_hidden_proto (__libc_dynarray_resize)
Packit Service 82fcde
libc_hidden_proto (__libc_dynarray_resize_clear)
Packit Service 82fcde
libc_hidden_proto (__libc_dynarray_finalize)
Packit Service 82fcde
libc_hidden_proto (__libc_dynarray_at_failure)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#endif /* _DYNARRAY_H */