diff options
Diffstat (limited to 'libsimple/realloc.h')
-rw-r--r-- | libsimple/realloc.h | 260 |
1 files changed, 259 insertions, 1 deletions
diff --git a/libsimple/realloc.h b/libsimple/realloc.h index 2d8af2e..32a5f59 100644 --- a/libsimple/realloc.h +++ b/libsimple/realloc.h @@ -215,7 +215,7 @@ libsimple_enreallocn(int __status, void *__ptr, size_t __n, ... /*, (size_t)0 */ */ _LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_erealloc(void *__ptr, size_t __n) -{ return enrealloc(libsimple_default_failure_exit, __ptr, __n); } +{ return libsimple_enrealloc(libsimple_default_failure_exit, __ptr, __n); } #ifndef erealloc # define erealloc libsimple_erealloc #endif @@ -299,3 +299,261 @@ libsimple_ereallocn(void *__ptr, size_t __n, ... /*, (size_t)0 */) #ifndef ereallocn # define ereallocn libsimple_ereallocn #endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is deallocated. If `ptr` + * is `NULL` a new allocation is made. + * + * The allocation size will be at least `n * m` + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)`; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2), __warn_unused_result__))) +static inline void * +libsimple_reallocf(void *__ptr, size_t __n) /* TODO test */ +{ + void *__new = __n ? realloc(__ptr, __n) : NULL; + if (!__new) + free(__ptr); + return __new; +} +#ifndef reallocf +# define reallocf libsimple_reallocf +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is still valid. If `ptr` + * is `NULL` a new allocation is made. + * + * The allocation size will be at least `n * m` + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n The number of elements to allocate, the behaviour of + * this function is unspecified for the value 0 + * @param m Size, in bytes, of each element, the behaviour of + * this function is unspecified for the value 0 + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)`; `NULL` on failure + * @throws EINVAL `n` or `m` is 0 + * @throws ENOMEM Could not allocated enough memory + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2, 3), __warn_unused_result__))) +static inline void * +libsimple_reallocarray(void *__ptr, size_t __n, size_t __m) +{ + if (LIBSIMPLE_UMUL_OVERFLOW(__n, __m, &__n, SIZE_MAX)) { + errno = ENOMEM; + return NULL; + } + return realloc(__ptr, __n); +} +#ifndef reallocarray +# define reallocarray libsimple_reallocarray +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is still valid. If `ptr` + * is `NULL` a new allocation is made. + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * The allocation size will be at least `n * m` + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n The number of elements to allocate, the behaviour of + * this function is unspecified for the value 0 + * @param m Size, in bytes, of each element, the behaviour of + * this function is unspecified for the value 0 + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)` + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(3, 4), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enreallocarray(int, void *, size_t, size_t); +#ifndef enreallocarray +# define enreallocarray libsimple_enreallocarray +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is still valid. If `ptr` + * is `NULL` a new allocation is made. + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * The allocation size will be at least `n * m` + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n The number of elements to allocate, the behaviour of + * this function is unspecified for the value 0 + * @param m Size, in bytes, of each element, the behaviour of + * this function is unspecified for the value 0 + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)` + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2, 3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ereallocarray(void *__ptr, size_t __n, size_t __m) +{ return libsimple_enreallocarray(libsimple_default_failure_exit, __ptr, __n, __m); } +#ifndef ereallocarray +# define ereallocarray libsimple_ereallocarray +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is deallocated. If `ptr` + * is `NULL` a new allocation is made. + * + * The allocation size will be at least `n * m` + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n The number of elements to allocate, the behaviour of + * this function is unspecified for the value 0 + * @param m Size, in bytes, of each element, the behaviour of + * this function is unspecified for the value 0 + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)`; `NULL` on failure + * @throws EINVAL `n` or `m` is 0 + * @throws ENOMEM Could not allocated enough memory + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2, 3), __warn_unused_result__))) +static inline void * +libsimple_reallocarrayf(void *__ptr, size_t __n, size_t __m) /* TODO test */ +{ + void *__new = __n ? libsimple_reallocarray(__ptr, __n, __m) : NULL; + if (!__new) + free(__ptr); + return __new; +} +#ifndef reallocarrayf +# define reallocarrayf libsimple_reallocarrayf +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is deallocated. If `ptr` + * is `NULL` a new allocation is made. + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n First factor for the allocation size, must not be 0 + * @param ap The rest of the factors for the allocation size, + * all arguments should have the type `size_t`, and + * list must end with 0 (which is not factor) + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)`; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +static inline void * +libsimple_vreallocfn(void *__ptr, size_t __n, va_list __ap) /* TODO test (reallocfn) */ +{ + void *__new = libsimple_vreallocn(__ptr, __n, __ap); + if (!__new) + free(__ptr); + return __new; +} +#ifndef vreallocfn +# define vreallocfn libsimple_vreallocfn +#endif + + +/** + * Dynamically reallocates heap allocated, uninitialised, + * memory with default alignment (`alignof(max_align_t)`) + * as the new alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * On success, either `ptr` is returned, or a new non-null + * pointer is returned with the same content (truncated to + * `n` bytes if size shrunk), in which case `ptr` is + * deallocated. On failure `ptr` is deallocated. If `ptr` + * is `NULL` a new allocation is made. + * + * @param ptr Pointer to reallocated, `NULL` for a new allocation + * @param n First factor for the allocation size, must not be 0 + * @param ... The rest of the factors for the allocation size, + * all arguments should have the type `size_t`, and + * list must end with 0 (which is not factor) + * @return Either `ptr` or a unique pointer with at least + * the specified size and with the alignment + * `alignof(max_align_t)`; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +static inline void * +libsimple_reallocfn(void *__ptr, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vreallocfn(__ptr, __n, __ap); + va_end(__ap); +} +#ifndef reallocfn +# define reallocfn libsimple_reallocfn +#endif |