2017-06-02 17:59:28 +08:00
|
|
|
/* Type-safe arrays which grow dynamically. Shared definitions.
|
2022-01-02 02:54:23 +08:00
|
|
|
Copyright (C) 2017-2022 Free Software Foundation, Inc.
|
2017-06-02 17:59:28 +08:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2017-06-02 17:59:28 +08:00
|
|
|
|
|
|
|
/* To use the dynarray facility, you need to include
|
|
|
|
<malloc/dynarray-skeleton.c> and define the parameter macros
|
|
|
|
documented in that file.
|
|
|
|
|
|
|
|
A minimal example which provides a growing list of integers can be
|
|
|
|
defined like this:
|
|
|
|
|
|
|
|
struct int_array
|
|
|
|
{
|
|
|
|
// Pointer to result array followed by its length,
|
|
|
|
// as required by DYNARRAY_FINAL_TYPE.
|
|
|
|
int *array;
|
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DYNARRAY_STRUCT dynarray_int
|
|
|
|
#define DYNARRAY_ELEMENT int
|
|
|
|
#define DYNARRAY_PREFIX dynarray_int_
|
|
|
|
#define DYNARRAY_FINAL_TYPE struct int_array
|
|
|
|
#include <malloc/dynarray-skeleton.c>
|
|
|
|
|
|
|
|
To create a three-element array with elements 1, 2, 3, use this
|
|
|
|
code:
|
|
|
|
|
|
|
|
struct dynarray_int dyn;
|
|
|
|
dynarray_int_init (&dyn);
|
|
|
|
for (int i = 1; i <= 3; ++i)
|
|
|
|
{
|
|
|
|
int *place = dynarray_int_emplace (&dyn);
|
|
|
|
assert (place != NULL);
|
|
|
|
*place = i;
|
|
|
|
}
|
|
|
|
struct int_array result;
|
|
|
|
bool ok = dynarray_int_finalize (&dyn, &result);
|
|
|
|
assert (ok);
|
|
|
|
assert (result.length == 3);
|
|
|
|
assert (result.array[0] == 1);
|
|
|
|
assert (result.array[1] == 2);
|
|
|
|
assert (result.array[2] == 3);
|
|
|
|
free (result.array);
|
|
|
|
|
|
|
|
If the elements contain resources which must be freed, define
|
|
|
|
DYNARRAY_ELEMENT_FREE appropriately, like this:
|
|
|
|
|
|
|
|
struct str_array
|
|
|
|
{
|
|
|
|
char **array;
|
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DYNARRAY_STRUCT dynarray_str
|
|
|
|
#define DYNARRAY_ELEMENT char *
|
|
|
|
#define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
|
|
|
|
#define DYNARRAY_PREFIX dynarray_str_
|
|
|
|
#define DYNARRAY_FINAL_TYPE struct str_array
|
|
|
|
#include <malloc/dynarray-skeleton.c>
|
|
|
|
|
|
|
|
Compared to scratch buffers, dynamic arrays have the following
|
|
|
|
features:
|
|
|
|
|
|
|
|
- They have an element type, and are not just an untyped buffer of
|
|
|
|
bytes.
|
|
|
|
|
|
|
|
- When growing, previously stored elements are preserved. (It is
|
|
|
|
expected that scratch_buffer_grow_preserve and
|
|
|
|
scratch_buffer_set_array_size eventually go away because all
|
|
|
|
current users are moved to dynamic arrays.)
|
|
|
|
|
|
|
|
- Scratch buffers have a more aggressive growth policy because
|
|
|
|
growing them typically means a retry of an operation (across an
|
|
|
|
NSS service module boundary), which is expensive.
|
|
|
|
|
|
|
|
- For the same reason, scratch buffers have a much larger initial
|
|
|
|
stack allocation. */
|
|
|
|
|
|
|
|
#ifndef _DYNARRAY_H
|
|
|
|
#define _DYNARRAY_H
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
struct dynarray_header
|
|
|
|
{
|
|
|
|
size_t used;
|
|
|
|
size_t allocated;
|
|
|
|
void *array;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Marker used in the allocated member to indicate that an error was
|
|
|
|
encountered. */
|
|
|
|
static inline size_t
|
|
|
|
__dynarray_error_marker (void)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Internal function. See the has_failed function in
|
|
|
|
dynarray-skeleton.c. */
|
|
|
|
static inline bool
|
|
|
|
__dynarray_error (struct dynarray_header *list)
|
|
|
|
{
|
|
|
|
return list->allocated == __dynarray_error_marker ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Internal function. Enlarge the dynamically allocated area of the
|
|
|
|
array to make room for one more element. SCRATCH is a pointer to
|
|
|
|
the scratch area (which is not heap-allocated and must not be
|
|
|
|
freed). ELEMENT_SIZE is the size, in bytes, of one element.
|
|
|
|
Return false on failure, true on success. */
|
|
|
|
bool __libc_dynarray_emplace_enlarge (struct dynarray_header *,
|
|
|
|
void *scratch, size_t element_size);
|
|
|
|
|
|
|
|
/* Internal function. Enlarge the dynamically allocated area of the
|
|
|
|
array to make room for at least SIZE elements (which must be larger
|
|
|
|
than the existing used part of the dynamic array). SCRATCH is a
|
|
|
|
pointer to the scratch area (which is not heap-allocated and must
|
|
|
|
not be freed). ELEMENT_SIZE is the size, in bytes, of one element.
|
|
|
|
Return false on failure, true on success. */
|
|
|
|
bool __libc_dynarray_resize (struct dynarray_header *, size_t size,
|
|
|
|
void *scratch, size_t element_size);
|
|
|
|
|
|
|
|
/* Internal function. Like __libc_dynarray_resize, but clear the new
|
|
|
|
part of the dynamic array. */
|
|
|
|
bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size,
|
|
|
|
void *scratch, size_t element_size);
|
|
|
|
|
|
|
|
/* Internal type. */
|
|
|
|
struct dynarray_finalize_result
|
|
|
|
{
|
|
|
|
void *array;
|
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Internal function. Copy the dynamically-allocated area to an
|
|
|
|
explicitly-sized heap allocation. SCRATCH is a pointer to the
|
|
|
|
embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the
|
|
|
|
element type. On success, true is returned, and pointer and length
|
|
|
|
are written to *RESULT. On failure, false is returned. The caller
|
|
|
|
has to take care of some of the memory management; this function is
|
|
|
|
expected to be called from dynarray-skeleton.c. */
|
|
|
|
bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
|
|
|
|
size_t element_size,
|
|
|
|
struct dynarray_finalize_result *result);
|
|
|
|
|
|
|
|
|
|
|
|
/* Internal function. Terminate the process after an index error.
|
|
|
|
SIZE is the number of elements of the dynamic array. INDEX is the
|
|
|
|
lookup index which triggered the failure. */
|
malloc: Sync dynarray with gnulib
It syncs with gnulib version a8bac4d49. The main changes are:
- Remove the usage of anonymous union within DYNARRAY_STRUCT.
- Use DYNARRAY_FREE instead of DYNARRAY_NAME (free) so that
Gnulib does not change 'free' to 'rpl_free'.
- Use __nonnull instead of __attribute__ ((nonnull ())).
- Use __attribute_maybe_unused__ instead of
__attribute__ ((unused, nonnull (1))).
- Use of _Noreturn instead of _attribute__ ((noreturn)).
The only difference with gnulib is:
--- glibc
+++ gnulib
@@ -18,6 +18,7 @@
#include <dynarray.h>
#include <stdio.h>
+#include <stdlib.h>
void
__libc_dynarray_at_failure (size_t size, size_t index)
@@ -27,7 +28,6 @@
__snprintf (buf, sizeof (buf), "Fatal glibc error: "
"array index %zu not less than array length %zu\n",
index, size);
- __libc_fatal (buf);
#else
abort ();
#endif
It seems a wrong sync from gnulib (the code is used on loader and
thus it requires __libc_fatal instead of abort).
Checked on x86_64-linux-gnu.
2021-01-11 23:03:38 +08:00
|
|
|
_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
|
2017-06-19 18:58:08 +08:00
|
|
|
|
|
|
|
#ifndef _ISOMAC
|
|
|
|
libc_hidden_proto (__libc_dynarray_emplace_enlarge)
|
|
|
|
libc_hidden_proto (__libc_dynarray_resize)
|
|
|
|
libc_hidden_proto (__libc_dynarray_resize_clear)
|
|
|
|
libc_hidden_proto (__libc_dynarray_finalize)
|
2017-06-02 17:59:28 +08:00
|
|
|
libc_hidden_proto (__libc_dynarray_at_failure)
|
2017-06-19 18:58:08 +08:00
|
|
|
#endif
|
2017-06-02 17:59:28 +08:00
|
|
|
|
|
|
|
#endif /* _DYNARRAY_H */
|