pmt: initial 3.0.2 update

This commit is contained in:
2024-12-14 10:25:23 +03:00
parent 686ef38598
commit 7f8090bb1f
1292 changed files with 500876 additions and 2823 deletions

View File

@@ -0,0 +1,177 @@
/* Type-safe arrays which grow dynamically. Shared definitions.
Copyright (C) 2017-2024 Free Software Foundation, Inc.
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
<https://www.gnu.org/licenses/>. */
/* 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 <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. */
_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
#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)
libc_hidden_proto (__libc_dynarray_at_failure)
#endif
#endif /* _DYNARRAY_H */

View File

@@ -0,0 +1,135 @@
/* Variable-sized buffer with on-stack default allocation.
Copyright (C) 2015-2024 Free Software Foundation, Inc.
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
<https://www.gnu.org/licenses/>. */
#ifndef _SCRATCH_BUFFER_H
#define _SCRATCH_BUFFER_H
/* Scratch buffers with a default stack allocation and fallback to
heap allocation. It is expected that this function is used in this
way:
struct scratch_buffer tmpbuf;
scratch_buffer_init (&tmpbuf);
while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
if (!scratch_buffer_grow (&tmpbuf))
return -1;
scratch_buffer_free (&tmpbuf);
return 0;
The allocation functions (scratch_buffer_grow,
scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
sure that the heap allocation, if any, is freed, so that the code
above does not have a memory leak. The buffer still remains in a
state that can be deallocated using scratch_buffer_free, so a loop
like this is valid as well:
struct scratch_buffer tmpbuf;
scratch_buffer_init (&tmpbuf);
while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
if (!scratch_buffer_grow (&tmpbuf))
break;
scratch_buffer_free (&tmpbuf);
scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
to grow the buffer by at least 512 bytes. This means that when
using the scratch buffer as a backing store for a non-character
array whose element size, in bytes, is 512 or smaller, the scratch
buffer only has to grow once to make room for at least one more
element.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
/* Scratch buffer. Must be initialized with scratch_buffer_init
before its use. */
struct scratch_buffer {
void *data; /* Pointer to the beginning of the scratch area. */
size_t length; /* Allocated space at the data pointer, in bytes. */
union { max_align_t __align; char __c[1024]; } __space;
};
/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
and BUFFER->length reflects the available space. */
static inline void
scratch_buffer_init (struct scratch_buffer *buffer)
{
buffer->data = buffer->__space.__c;
buffer->length = sizeof (buffer->__space);
}
/* Deallocates *BUFFER (if it was heap-allocated). */
static inline void
scratch_buffer_free (struct scratch_buffer *buffer)
{
if (buffer->data != buffer->__space.__c)
free (buffer->data);
}
/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
preserved. Return true on success, false on allocation failure (in
which case the old buffer is freed). On success, the new buffer is
larger than the previous size. On failure, *BUFFER is deallocated,
but remains in a free-able state, and errno is set. */
bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
libc_hidden_proto (__libc_scratch_buffer_grow)
/* Alias for __libc_scratch_buffer_grow. */
static __always_inline bool
scratch_buffer_grow (struct scratch_buffer *buffer)
{
return __glibc_likely (__libc_scratch_buffer_grow (buffer));
}
/* Like __libc_scratch_buffer_grow, but preserve the old buffer
contents on success, as a prefix of the new buffer. */
bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
libc_hidden_proto (__libc_scratch_buffer_grow_preserve)
/* Alias for __libc_scratch_buffer_grow_preserve. */
static __always_inline bool
scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
{
return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer));
}
/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
can be zero. Return true on success, false on allocation failure
(in which case the old buffer is freed, but *BUFFER remains in a
free-able state, and errno is set). It is unspecified whether this
function can reduce the array size. */
bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
size_t nelem, size_t size);
libc_hidden_proto (__libc_scratch_buffer_set_array_size)
/* Alias for __libc_scratch_set_array_size. */
static __always_inline bool
scratch_buffer_set_array_size (struct scratch_buffer *buffer,
size_t nelem, size_t size)
{
return __glibc_likely (__libc_scratch_buffer_set_array_size
(buffer, nelem, size));
}
#endif /* _SCRATCH_BUFFER_H */