array: improve pw_array

Handle extend == 0 and don't expand the array but return -ENOSPC.
This makes it possible to handle static arrays, make a function to
make this easier. Remove pw_array_add_fixed() now that we support
this with extend==0 and because it was not used.

Round up the required space to next extend so that the total allocated
size if always a multiple of the extend.

Make pw_array_add_ptr() check for allocation errors instead of crashing.
This commit is contained in:
Wim Taymans 2024-01-12 12:06:13 +01:00
parent 0f533c6d64
commit adbd081b12

View file

@ -29,7 +29,8 @@ struct pw_array {
void *data; /**< pointer to array data */ void *data; /**< pointer to array data */
size_t size; /**< length of array in bytes */ size_t size; /**< length of array in bytes */
size_t alloc; /**< number of allocated memory in \a data */ size_t alloc; /**< number of allocated memory in \a data */
size_t extend; /**< number of bytes to extend with */ size_t extend; /**< number of bytes to extend with, 0 when the
* data should not expand */
}; };
/** Initialize an array. The new array is empty. */ /** Initialize an array. The new array is empty. */
@ -68,7 +69,8 @@ struct pw_array {
SPA_PTRDIFF(pw_array_end(a),(p))); \ SPA_PTRDIFF(pw_array_end(a),(p))); \
}) })
/** Initialize the array with given extend */ /** Initialize the array with given extend. Extend needs to be > 0 or else
* the array will not be able to expand. */
static inline void pw_array_init(struct pw_array *arr, size_t extend) static inline void pw_array_init(struct pw_array *arr, size_t extend)
{ {
arr->data = NULL; arr->data = NULL;
@ -76,13 +78,22 @@ static inline void pw_array_init(struct pw_array *arr, size_t extend)
arr->extend = extend; arr->extend = extend;
} }
/** Clear the array */ /** Clear the array. This should be called when pw_array_init() was called. */
static inline void pw_array_clear(struct pw_array *arr) static inline void pw_array_clear(struct pw_array *arr)
{ {
free(arr->data); if (arr->extend > 0)
free(arr->data);
pw_array_init(arr, arr->extend); pw_array_init(arr, arr->extend);
} }
/** Initialize a static array. */
static inline void pw_array_init_static(struct pw_array *arr, void *data, size_t size)
{
arr->data = data;
arr->alloc = size;
arr->size = arr->extend = 0;
}
/** Reset the array */ /** Reset the array */
static inline void pw_array_reset(struct pw_array *arr) static inline void pw_array_reset(struct pw_array *arr)
{ {
@ -99,10 +110,9 @@ static inline int pw_array_ensure_size(struct pw_array *arr, size_t size)
if (SPA_UNLIKELY(alloc < need)) { if (SPA_UNLIKELY(alloc < need)) {
void *data; void *data;
alloc = SPA_MAX(alloc, arr->extend); if (arr->extend == 0)
spa_assert(alloc != 0); /* forgot pw_array_init */ return -ENOSPC;
while (alloc < need) alloc = SPA_ROUND_UP(need, arr->extend);
alloc *= 2;
if (SPA_UNLIKELY((data = realloc(arr->data, alloc)) == NULL)) if (SPA_UNLIKELY((data = realloc(arr->data, alloc)) == NULL))
return -errno; return -errno;
arr->data = data; arr->data = data;
@ -127,27 +137,17 @@ static inline void *pw_array_add(struct pw_array *arr, size_t size)
return p; return p;
} }
/** Add \a ref size bytes to \a arr. When there is not enough memory to /** Add a pointer to array. Returns 0 on success and a negative errno style
* hold \a size bytes, NULL is returned */ * error on failure. */
static inline void *pw_array_add_fixed(struct pw_array *arr, size_t size) static inline int pw_array_add_ptr(struct pw_array *arr, void *ptr)
{ {
void *p; void **p = (void **)pw_array_add(arr, sizeof(void*));
if (p == NULL)
if (SPA_UNLIKELY(arr->alloc < arr->size + size)) { return -errno;
errno = ENOSPC; *p = ptr;
return NULL; return 0;
}
p = SPA_PTROFF(arr->data, arr->size, void);
arr->size += size;
return p;
} }
/** Add a pointer to array */
#define pw_array_add_ptr(a,p) \
*((void**) pw_array_add(a, sizeof(void*))) = (p)
/** /**
* \} * \}
*/ */