diff options
-rw-r--r-- | libsimple.h | 50 | ||||
-rw-r--r-- | libsimple/aligned_alloc.h | 151 | ||||
-rw-r--r-- | libsimple/aligned_allocz.h | 179 | ||||
-rw-r--r-- | libsimple/definitions.h | 83 | ||||
-rw-r--r-- | libsimple/memalign.h | 169 | ||||
-rw-r--r-- | libsimple/memalignz.h | 178 | ||||
-rw-r--r-- | libsimple/posix_memalign.h | 181 | ||||
-rw-r--r-- | libsimple/posix_memalignz.h | 209 | ||||
-rw-r--r-- | libsimple/printf.h | 181 | ||||
-rw-r--r-- | libsimple/pvalloc.h | 191 | ||||
-rw-r--r-- | libsimple/pvallocz.h | 202 | ||||
-rw-r--r-- | libsimple/valloc.h | 154 | ||||
-rw-r--r-- | libsimple/vallocz.h | 165 | ||||
-rw-r--r-- | man/libsimple_aligned_memdup.3 | 4 | ||||
-rw-r--r-- | man/libsimple_enstrdup.3 | 4 | ||||
-rw-r--r-- | man/libsimple_enstrndup.3 | 4 | ||||
-rw-r--r-- | man/libsimple_memdup.3 | 4 | ||||
-rw-r--r-- | vweprintf.c | 4 |
18 files changed, 2068 insertions, 45 deletions
diff --git a/libsimple.h b/libsimple.h index 96cd73c..8020926 100644 --- a/libsimple.h +++ b/libsimple.h @@ -47,6 +47,11 @@ #endif +/** + * Exit value for `libsimple_eprintf` + * + * Default value is 1 + */ extern int libsimple_default_failure_exit; @@ -82,6 +87,17 @@ extern int libsimple_default_failure_exit; #define CLOSE(FD) libsimple_close(&(FD)) + +/** + * Wrapper for close(3) that only calls close(3) + * if the file descriptor number is non-negative, + * and that will set it to -1 after closing + * + * @param fdp Pointer to file descriptor number, will + * be update to -1 if it is non-negative + * @return Return value of close(3) (0 on success, + * -1 on error), 0 if `*fdp < 0` + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) static inline int libsimple_close(int *__fdp) @@ -94,6 +110,15 @@ libsimple_close(int *__fdp) return __ret; } + +/** + * Check whether a byte is in a string of bytes + * + * @param c The byte to look for, will not be found if it is the NUL byte + * @param s The string to look in + * @return 1 if the byte `c` is not the NUL byte and can be found in `s`, + * 0 otherwise + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) static inline int libsimple_inchrset(int __c, const char *__s) { return __c && strchr(__s, __c); } @@ -101,11 +126,13 @@ static inline int libsimple_inchrset(int __c, const char *__s) # define inchrset libsimple_inchrset #endif + /** * Check whether a NUL-terminated string is encoded in UTF-8 * * @param string The string - * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL + * @param allow_modified_nul Whether Modified UTF-8 is allowed, which + * allows a two-byte encoding for NUL * @return 1 if good, 0 on encoding error */ _LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) @@ -114,11 +141,32 @@ int libsimple_isutf8(const char *, int); # define isutf8 libsimple_isutf8 #endif + +/** + * Remove an item from a list, keeping the list ordered + * + * `list` must be non-void pointer to a complete type, + * the type of the pointer will be used to infer the + * width of the items in the list + * + * @param list:non-void pointer The list + * @param i:size_t The index of the item to remove + * @param n:size_t Pointer to the number of items in the list, will be updated + */ #define LIBSIMPLE_UNLIST(LIST, I, NP) libsimple_unlist((LIST), (I), (NP), sizeof(*(LIST))) #ifndef UNLIST # define UNLIST(LIST, I, NP) LIBSIMPLE_UNLIST((LIST), (I), (NP)) #endif + +/** + * Remove an item from a list, keeping the list ordered + * + * @param list The list + * @param i The index of the item to remove + * @param n Pointer to the number of items in the list, will be updated + * @param width The width, in bytes, of each item in the list + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) static inline void libsimple_unlist(void *__list, size_t __i, size_t *__np, size_t __width) diff --git a/libsimple/aligned_alloc.h b/libsimple/aligned_alloc.h index 6155c7d..b2a60f1 100644 --- a/libsimple/aligned_alloc.h +++ b/libsimple/aligned_alloc.h @@ -1,10 +1,24 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2. - * Allocation size must be a mutiple of the alignment. - */ +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) static inline void *libsimple_valigned_allocn(size_t __alignment, size_t __n, va_list __ap) { return libsimple_valigned_alloczn(0, __alignment, __n, __ap); } @@ -12,6 +26,18 @@ static inline void *libsimple_valigned_allocn(size_t __alignment, size_t __n, va # define valigned_allocn libsimple_valigned_allocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) static inline void * libsimple_aligned_allocn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -25,6 +51,22 @@ libsimple_aligned_allocn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) # define aligned_allocn libsimple_aligned_allocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_enaligned_alloc(int __status, size_t __alignment, size_t __n) { return libsimple_enaligned_allocz(__status, 0, __alignment, __n); } @@ -32,6 +74,28 @@ static inline void *libsimple_enaligned_alloc(int __status, size_t __alignment, # define enaligned_alloc libsimple_enaligned_alloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envaligned_allocn(int __status, size_t __alignment, size_t __n, va_list __ap) { return libsimple_envaligned_alloczn(__status, 0, __alignment, __n, __ap); } @@ -39,6 +103,28 @@ static inline void *libsimple_envaligned_allocn(int __status, size_t __alignment # define envaligned_allocn libsimple_envaligned_allocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enaligned_allocn(int __status, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -52,6 +138,21 @@ libsimple_enaligned_allocn(int __status, size_t __alignment, size_t __n, ... /*, # define enaligned_allocn libsimple_enaligned_allocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_ealigned_alloc(size_t __alignment, size_t __n) { return libsimple_enaligned_alloc(libsimple_default_failure_exit, __alignment, __n); } @@ -59,6 +160,27 @@ static inline void *libsimple_ealigned_alloc(size_t __alignment, size_t __n) # define ealigned_alloc libsimple_ealigned_alloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evaligned_allocn(size_t __alignment, size_t __n, va_list __ap) { return libsimple_envaligned_allocn(libsimple_default_failure_exit, __alignment, __n, __ap); } @@ -66,6 +188,27 @@ static inline void *libsimple_evaligned_allocn(size_t __alignment, size_t __n, v # define evaligned_allocn libsimple_evaligned_allocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ealigned_allocn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/aligned_allocz.h b/libsimple/aligned_allocz.h index 1c81697..9380a50 100644 --- a/libsimple/aligned_allocz.h +++ b/libsimple/aligned_allocz.h @@ -1,16 +1,45 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2. - * Allocation size must be a mutiple of the alignment. - */ +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) void *libsimple_valigned_alloczn(int, size_t, size_t, va_list); #ifndef valigned_alloczn # define valigned_alloczn libsimple_valigned_alloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__))) static inline void * libsimple_aligned_allocz(int __clear, size_t __alignment, size_t __n) @@ -24,6 +53,26 @@ libsimple_aligned_allocz(int __clear, size_t __alignment, size_t __n) # define aligned_allocz libsimple_aligned_allocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) static inline void * libsimple_aligned_alloczn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -37,18 +86,81 @@ libsimple_aligned_alloczn(int __clear, size_t __alignment, size_t __n, ... /*, ( # define aligned_alloczn libsimple_aligned_alloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __alloc_size__(4), __warn_unused_result__, __returns_nonnull__))) void *libsimple_enaligned_allocz(int, int, size_t, size_t); #ifndef enaligned_allocz # define enaligned_allocz libsimple_enaligned_allocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, + * `clear`, and `alignment`, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) void *libsimple_envaligned_alloczn(int, int, size_t, size_t, va_list); #ifndef envaligned_alloczn # define envaligned_alloczn libsimple_envaligned_alloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, + * `clear`, and `alignment`, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enaligned_alloczn(int __status, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -62,6 +174,21 @@ libsimple_enaligned_alloczn(int __status, int __clear, size_t __alignment, size_ # define enaligned_alloczn libsimple_enaligned_alloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_ealigned_allocz(int __clear, size_t __alignment, size_t __n) { return libsimple_enaligned_allocz(libsimple_default_failure_exit, __clear, __alignment, __n); } @@ -69,6 +196,28 @@ static inline void *libsimple_ealigned_allocz(int __clear, size_t __alignment, s # define ealigned_allocz libsimple_ealigned_allocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evaligned_alloczn(int __clear, size_t __alignment, size_t __n, va_list __ap) { return libsimple_envaligned_alloczn(libsimple_default_failure_exit, __clear, __alignment, __n, __ap); } @@ -76,6 +225,28 @@ static inline void *libsimple_evaligned_alloczn(int __clear, size_t __alignment, # define evaligned_alloczn libsimple_evaligned_alloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ealigned_alloczn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/definitions.h b/libsimple/definitions.h index 9bbc649..0ff2677 100644 --- a/libsimple/definitions.h +++ b/libsimple/definitions.h @@ -108,45 +108,126 @@ #endif +/** + * Get the smallest of two numerical values + * + * @param A One of the values + * @param B The other value + * @return The smallest of `A` and `B` + */ #ifndef MIN # define MIN(A, B) ((A) < (B) ? (A) : (B)) #endif + +/** + * Get the largest of two numerical values + * + * @param A One of the values + * @param B The other value + * @return The largest of `A` and `B` + */ #ifndef MAX # define MAX(A, B) ((A) > (B) ? (A) : (B)) #endif + +/** + * Get the smallest of three numerical values + * + * @param A One of the values + * @param B Another one of the values + * @param C The last value + * @return The smallest of `A`, `B`, and `C` + */ #ifndef MIN3 # define MIN3(A, B, C) MIN(MIN((A), (B)), (C)) #endif + +/** + * Get the largest of three numerical values + * + * @param A One of the values + * @param B Another one of the values + * @param C The last value + * @return The largest of `A`, `B`, and `C` + */ #ifndef MAX3 # define MAX3(A, B, C) MAX(MAX((A), (B)), (C)) #endif +/** + * Get the number of elements in an array + * + * @param ARR The array, must not be a pointer + * @return :size_t The number of elements in `ARR` (constant + * expression, unless its size is dynamic) + */ #ifndef ELEMSOF # define ELEMSOF(ARR) (sizeof(ARR) / (sizeof(*(ARR)))) #endif + +/** + * Get the length of a string literal + * + * This macro does not support the wide-character strings + * + * @param STR:const char [] The string, must be a literal + * @return :size_t The value of `strlen(STR)` as a constant expression + */ #ifndef STRLEN # define STRLEN(STR) (sizeof(STR) - 1) #endif + +/** + * Get an approximation for the longest string an + * integer of the specific integer type can be + * converted to assuming it will not having an + * explicit '+' sign or any leading zeroes or + * other superfluous characters + * + * The calculated approximation will not be less + * than the real limit + * + * @param TYPE:integer type The type, must be an integer type, may be signed or unsigned + * @return :size_t A value close to, but not less than, the longest string a + * value of the type `TYPE` can be converted to without any + * superfluous characters (such as explitict '+' or leading zeroes') + * (constant expression) + */ #ifndef INTSTRLEN # define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : 5 * (sizeof(TYPE) / 2)) + ((TYPE)-1 < 0)) #endif +/** + * Get the maximum value for an integer type + * + * @param TYPE:integer type The type, must be an integer type, may be signed or unsigned + * @return :TYPE The largest value that can be stored in `TYPE` (constant expression) + */ #ifndef TYPE_MAX # define TYPE_MAX(TYPE) ((TYPE)(((1ULL << (8 * sizeof(TYPE) - 1)) - 1) << ((TYPE)-1 > 0) | 1)) #endif + +/** + * Get the minimum value for an integer type + * + * @param TYPE:integer type The type, must be an integer type, may be signed or unsigned + * @return :TYPE The smallest value that can be stored in `TYPE` (constant expression) + */ #ifndef TYPE_MIN # define TYPE_MIN(TYPE) ((TYPE)((TYPE)-1 > 0 ? 0 : (TYPE)~0 < (TYPE)-1 ? (TYPE)~0 : (TYPE)(1ULL << (8 * sizeof(TYPE) - 1)))) #endif +/* --- Maximum values --- */ + #ifndef BLKCNT64_MAX # define BLKCNT64_MAX TYPE_MAX(blkcnt64_t) #endif @@ -284,6 +365,8 @@ #endif +/* --- Minimum values --- */ + #ifndef BLKCNT64_MIN # define BLKCNT64_MIN TYPE_MIN(blkcnt64_t) #endif diff --git a/libsimple/memalign.h b/libsimple/memalign.h index 466de3e..169ec57 100644 --- a/libsimple/memalign.h +++ b/libsimple/memalign.h @@ -1,9 +1,24 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2. - */ +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) static inline void *libsimple_vmemalignn(size_t __alignment, size_t __n, va_list __ap) { return libsimple_vmemalignzn(0, __alignment, __n, __ap); } @@ -11,6 +26,18 @@ static inline void *libsimple_vmemalignn(size_t __alignment, size_t __n, va_list # define vmemalignn libsimple_vmemalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__))) static inline void *libsimple_memalign(size_t __alignment, size_t __n) { return libsimple_memalignz(0, __alignment, __n); } @@ -18,6 +45,25 @@ static inline void *libsimple_memalign(size_t __alignment, size_t __n) # define memalign libsimple_memalign #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) static inline void * libsimple_memalignn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -31,6 +77,22 @@ libsimple_memalignn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) # define memalignn libsimple_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_enmemalign(int __status, size_t __alignment, size_t __n) { return libsimple_enmemalignz(__status, 0, __alignment, __n); } @@ -38,6 +100,28 @@ static inline void *libsimple_enmemalign(int __status, size_t __alignment, size_ # define enmemalign libsimple_enmemalign #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envmemalignn(int __status, size_t __alignment, size_t __n, va_list __ap) { return libsimple_envmemalignzn(__status, 0, __alignment, __n, __ap); } @@ -45,6 +129,28 @@ static inline void *libsimple_envmemalignn(int __status, size_t __alignment, siz # define envmemalignn libsimple_envmemalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enmemalignn(int __status, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -58,6 +164,21 @@ libsimple_enmemalignn(int __status, size_t __alignment, size_t __n, ... /*, (siz # define enmemalignn libsimple_enmemalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_ememalign(size_t __alignment, size_t __n) { return libsimple_enmemalign(libsimple_default_failure_exit, __alignment, __n); } @@ -65,6 +186,27 @@ static inline void *libsimple_ememalign(size_t __alignment, size_t __n) # define ememalign libsimple_ememalign #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evmemalignn(size_t __alignment, size_t __n, va_list __ap) { return libsimple_envmemalignn(libsimple_default_failure_exit, __alignment, __n, __ap); } @@ -72,6 +214,27 @@ static inline void *libsimple_evmemalignn(size_t __alignment, size_t __n, va_lis # define evmemalignn libsimple_evmemalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `alignment`, + * up to the first 0, will be used as the number of + * bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ememalignn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/memalignz.h b/libsimple/memalignz.h index 4b47d0e..224443b 100644 --- a/libsimple/memalignz.h +++ b/libsimple/memalignz.h @@ -1,9 +1,25 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2. - */ +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) static inline void * libsimple_vmemalignzn(int __clear, size_t __alignment, size_t __n, va_list __ap) /* TODO test ([v]memalign[z]n) */ @@ -21,6 +37,19 @@ libsimple_vmemalignzn(int __clear, size_t __alignment, size_t __n, va_list __ap) # define vmemalignzn libsimple_vmemalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__))) static inline void * libsimple_memalignz(int __clear, size_t __alignment, size_t __n) /* TODO test (memalign[z]) */ @@ -38,6 +67,26 @@ libsimple_memalignz(int __clear, size_t __alignment, size_t __n) /* TODO test (m # define memalignz libsimple_memalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment; `NULL` on failure + * @throws EINVAL `n` is 0 or `alignment` is not a power of 2 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) static inline void * libsimple_memalignzn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -51,6 +100,23 @@ libsimple_memalignzn(int __clear, size_t __alignment, size_t __n, ... /*, (size_ # define memalignzn libsimple_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __alloc_size__(4), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enmemalignz(int __status, int __clear, size_t __alignment, size_t __n) /* TODO test (e[n]memalign[z]) */ @@ -68,6 +134,29 @@ libsimple_enmemalignz(int __status, int __clear, size_t __alignment, size_t __n) # define enmemalignz libsimple_enmemalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, + * `clear`, and `alignment`, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envmemalignzn(int __status, int __clear, size_t __alignment, size_t __n, va_list __ap) /* TODO test (e[n][v]memalign[z]n) */ @@ -86,6 +175,29 @@ libsimple_envmemalignzn(int __status, int __clear, size_t __alignment, size_t __ # define envmemalignzn libsimple_envmemalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, + * `clear`, and `alignment`, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enmemalignzn(int __status, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -99,6 +211,22 @@ libsimple_enmemalignzn(int __status, int __clear, size_t __alignment, size_t __n # define enmemalignzn libsimple_enmemalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_ememalignz(int __clear, size_t __alignment, size_t __n) { return libsimple_enmemalignz(libsimple_default_failure_exit, __alignment, __clear, __n); } @@ -106,6 +234,28 @@ static inline void *libsimple_ememalignz(int __clear, size_t __alignment, size_t # define ememalignz libsimple_ememalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evmemalignzn(int __clear, size_t __alignment, size_t __n, va_list __ap) { return libsimple_envmemalignzn(libsimple_default_failure_exit, __alignment, __clear, __n, __ap); } @@ -113,6 +263,28 @@ static inline void *libsimple_evmemalignzn(int __clear, size_t __alignment, size # define evmemalignzn libsimple_evmemalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `clear` and + * `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 + * @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 A unique pointer with at least the specified size + * and alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_ememalignzn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/posix_memalign.h b/libsimple/posix_memalign.h index 5443418..f656ea8 100644 --- a/libsimple/posix_memalign.h +++ b/libsimple/posix_memalign.h @@ -1,9 +1,30 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2 and a multiple of `sizeof(void *)`. - */ +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `memptr` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * @param memptr Output parameter for the new allocation, which + * will on successful completion be set to a unique + * pointer with at least the specified size and + * alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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 0 on success, the error code on failure (errno is + * not set) + * @throws EINVAL `n` is 0, `alignment` is not a power of 2, or + * `alignment` is not a multiple of `sizeof(void *)` + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline int libsimple_vposix_memalignn(void **__memptr, size_t __alignment, size_t __n, va_list __ap) { return libsimple_vposix_memalignzn(__memptr, 0, __alignment, __n, __ap); } @@ -11,6 +32,31 @@ static inline int libsimple_vposix_memalignn(void **__memptr, size_t __alignment # define vposix_memalignn libsimple_vposix_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `memptr` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * @param memptr Output parameter for the new allocation, which + * will on successful completion be set to a unique + * pointer with at least the specified size and + * alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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 0 on success, the error code on failure (errno is + * not set) + * @throws EINVAL `n` is 0, `alignment` is not a power of 2, or + * `alignment` is not a multiple of `sizeof(void *)` + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline int libsimple_posix_memalignn(void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -24,6 +70,24 @@ libsimple_posix_memalignn(void **__memptr, size_t __alignment, size_t __n, ... / # define posix_memalignn libsimple_posix_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) static inline void libsimple_enposix_memalign(int __status, void **__memptr, size_t __alignment, size_t __n) { libsimple_enposix_memalignz(__status, __memptr, 0, __alignment, __n); } @@ -31,6 +95,30 @@ static inline void libsimple_enposix_memalign(int __status, void **__memptr, siz # define enposix_memalign libsimple_enposix_memalign #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status`, `memptr`, + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) static inline void libsimple_envposix_memalignn(int __status, void **__memptr, size_t __alignment, size_t __n, va_list __ap) { libsimple_envposix_memalignzn(__status, __memptr, 0, __alignment, __n, __ap); } @@ -38,6 +126,30 @@ static inline void libsimple_envposix_memalignn(int __status, void **__memptr, s # define envposix_memalignn libsimple_envposix_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `status`, `memptr`, + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) static inline void libsimple_enposix_memalignn(int __status, void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -51,6 +163,23 @@ libsimple_enposix_memalignn(int __status, void **__memptr, size_t __alignment, s # define enposix_memalignn libsimple_enposix_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_eposix_memalign(void **__memptr, size_t __alignment, size_t __n) { libsimple_enposix_memalign(libsimple_default_failure_exit, __memptr, __alignment, __n); } @@ -58,6 +187,29 @@ static inline void libsimple_eposix_memalign(void **__memptr, size_t __alignment # define eposix_memalign libsimple_eposix_memalign #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `memptr` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_evposix_memalignn(void **__memptr, size_t __alignment, size_t __n, va_list __ap) { libsimple_envposix_memalignn(libsimple_default_failure_exit, __memptr, __alignment, __n, __ap); } @@ -65,6 +217,29 @@ static inline void libsimple_evposix_memalignn(void **__memptr, size_t __alignme # define evposix_memalignn libsimple_evposix_memalignn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with custom alignment + * + * The product of all arguments except `memptr` and + * `alignment`, up to the first 0, will be used as the + * number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_eposix_memalignn(void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/posix_memalignz.h b/libsimple/posix_memalignz.h index 2bbd310..323863d 100644 --- a/libsimple/posix_memalignz.h +++ b/libsimple/posix_memalignz.h @@ -1,15 +1,57 @@ /* See LICENSE file for copyright and license details. */ -/* - * Alignment must be a power of 2 and a multiple of `sizeof(void *)`. - */ +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `memptr`, `clear` + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param memptr Output parameter for the new allocation, which + * will on successful completion be set to a unique + * pointer with at least the specified size and + * alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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 0 on success, the error code on failure (errno is + * not set) + * @throws EINVAL `n` is 0, `alignment` is not a power of 2, or + * `alignment` is not a multiple of `sizeof(void *)` + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) int libsimple_vposix_memalignzn(void **, int, size_t, size_t, va_list); #ifndef vposix_memalignzn # define vposix_memalignzn libsimple_vposix_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * @param memptr Output parameter for the new allocation, which + * will on successful completion be set to a unique + * pointer with at least the specified size and + * alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return 0 on success, the error code on failure (errno is + * not set) + * @throws EINVAL `n` is 0, `alignment` is not a power of 2, or + * `alignment` is not a multiple of `sizeof(void *)` + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline int libsimple_posix_memalignz(void **__memptr, int __clear, size_t __alignment, size_t __n) @@ -23,6 +65,32 @@ libsimple_posix_memalignz(void **__memptr, int __clear, size_t __alignment, size # define posix_memalignz libsimple_posix_memalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `memptr`, `clear` + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * @param memptr Output parameter for the new allocation, which + * will on successful completion be set to a unique + * pointer with at least the specified size and + * alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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 0 on success, the error code on failure (errno is + * not set) + * @throws EINVAL `n` is 0, `alignment` is not a power of 2, or + * `alignment` is not a multiple of `sizeof(void *)` + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline int libsimple_posix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -36,18 +104,87 @@ libsimple_posix_memalignzn(void **__memptr, int __clear, size_t __alignment, siz # define posix_memalignzn libsimple_posix_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) void libsimple_enposix_memalignz(int, void **, int, size_t, size_t); #ifndef enposix_memalignz # define enposix_memalignz libsimple_enposix_memalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, `memptr`, + * `clear`, and `alignment`, up to the first 0, will be + * used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) void libsimple_envposix_memalignzn(int, void **, int, size_t, size_t, va_list); #ifndef envposix_memalignzn # define envposix_memalignzn libsimple_envposix_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `status`, `memptr`, + * `clear`, and `alignment`, up to the first 0, will be + * used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) static inline void libsimple_enposix_memalignzn(int __status, void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) @@ -61,6 +198,24 @@ libsimple_enposix_memalignzn(int __status, void **__memptr, int __clear, size_t # define enposix_memalignzn libsimple_enposix_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_eposix_memalignz(void **__memptr, int __clear, size_t __alignment, size_t __n) { libsimple_enposix_memalignz(libsimple_default_failure_exit, __memptr, __clear, __alignment, __n); } @@ -68,6 +223,30 @@ static inline void libsimple_eposix_memalignz(void **__memptr, int __clear, size # define eposix_memalignz libsimple_eposix_memalignz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `memptr`, `clear` + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_evposix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, va_list __ap) { libsimple_envposix_memalignzn(libsimple_default_failure_exit, __memptr, __clear, __alignment, __n, __ap); } @@ -75,6 +254,30 @@ static inline void libsimple_evposix_memalignzn(void **__memptr, int __clear, si # define evposix_memalignzn libsimple_evposix_memalignzn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with custom alignment + * + * The product of all arguments except `memptr`, `clear` + * and `alignment`, up to the first 0, will be used as + * the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param memptr Output parameter for the new allocation, which + * will be set to a unique pointer with at least the + * specified size and alignment + * @param clear Non-zero if the memory should be initialised + * @param alignment The alignment, must be a power of 2 and a multiple + * of `sizeof(void *)` + * @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) + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) static inline void libsimple_eposix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/printf.h b/libsimple/printf.h index f1e0b0d..9b6253c 100644 --- a/libsimple/printf.h +++ b/libsimple/printf.h @@ -1,17 +1,65 @@ /* See LICENSE file for copyright and license details. */ + +/** + * Version of `printf` that allocates, on the heap, a + * sufficiently large string and writes the output to it + * + * @param strp Output pointer for string, will be set to `NULL` + * on failure, however portable applications should + * assume that it may also be unmodified or a recently + * freed pointer if `asprintf` is used rather than + * `libsimple_asprintf` explicitly + * @param fmt The format string + * @param ... The format argument + * @return The length of the output on success, -1 on error + * @throws EMFILE {FOPEN_MAX} streams are currently open in the calling process + * @throws ENOMEM Could not allocate enough memory + * @throws Any error specified for `fprintf` + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2), __format__(__printf__, 2, 3)))) int libsimple_asprintf(char **, const char *, ...); #ifndef asprintf # define asprintf libsimple_asprintf #endif + +/** + * Version of `vprintf` that allocates, on the heap, a + * sufficiently large string and writes the output to it + * + * @param strp Output pointer for string, will be set to `NULL` + * on failure, however portable applications should + * assume that it may also be unmodified or a recently + * freed pointer if `asprintf` is used rather than + * `libsimple_asprintf` explicitly + * @param fmt The format string + * @param ap The format argument + * @return The length of the output on success, -1 on error + * @throws EMFILE {FOPEN_MAX} streams are currently open in the calling process + * @throws ENOMEM Could not allocate enough memory + * @throws Any error specified for `fprintf` + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) int libsimple_vasprintf(char **, const char *, va_list); #ifndef vasprintf # define vasprintf libsimple_vasprintf #endif + +/** + * Version of `printf` that allocates, on the stack, a + * sufficiently large string and writes the output to it + * + * This macro does not check whether it can allocate + * enough memory, if it cannot, the kernel may kill the + * thread, and possibly the process, with a SIGSEGV signal + * + * @param fmt The format string + * @param ... The format argument + * @return The formatted string, `NULL` on error + * @throws Any error specified for `snprintf` + */ #if defined(__GNUC__) || defined(__clang__) # define libsimple_asprintfa(__fmt, ...)\ ({\ @@ -29,6 +77,20 @@ int libsimple_vasprintf(char **, const char *, va_list); # endif #endif + +/** + * Version of `vprintf` that allocates, on the stack, a + * sufficiently large string and writes the output to it + * + * This macro does not check whether it can allocate + * enough memory, if it cannot, the kernel may kill the + * thread, and possibly the process, with a SIGSEGV signal + * + * @param fmt The format string + * @param ap The format argument + * @return The formatted string, `NULL` on error + * @throws Any error specified for `snprintf` + */ #if defined(__GNUC__) || defined(__clang__) # define libsimple_vasprintfa(__fmt, __ap)\ ({\ @@ -54,12 +116,47 @@ int libsimple_vasprintf(char **, const char *, va_list); #endif +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param fmt The format string + * @param ap The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) void libsimple_vweprintf(const char *, va_list); #ifndef vweprintf # define vweprintf libsimple_vweprintf #endif + +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param fmt The format string + * @param ... The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2)))) static inline void libsimple_weprintf(const char *__fmt, ...) @@ -73,6 +170,27 @@ libsimple_weprintf(const char *__fmt, ...) # define weprintf libsimple_weprintf #endif + +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * This function will exit the process + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param status Exit value for the process + * @param fmt The format string + * @param ap The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __noreturn__))) static inline void libsimple_venprintf(int __status, const char *__fmt, va_list __ap) @@ -84,6 +202,27 @@ libsimple_venprintf(int __status, const char *__fmt, va_list __ap) # define venprintf libsimple_venprintf #endif + +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * This function will exit the process + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param status Exit value for the process + * @param fmt The format string + * @param ... The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __format__(__printf__, 2, 3), __noreturn__))) static inline void libsimple_enprintf(int __status, const char *__fmt, ...) @@ -97,6 +236,27 @@ libsimple_enprintf(int __status, const char *__fmt, ...) # define enprintf libsimple_enprintf #endif + +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * This function will exit the process with the + * value `libsimple_default_failure_exit` + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param fmt The format string + * @param ap The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __noreturn__))) static inline void libsimple_veprintf(const char *__fmt, va_list __ap) @@ -108,6 +268,27 @@ libsimple_veprintf(const char *__fmt, va_list __ap) # define veprintf libsimple_veprintf #endif + +/** + * Version of `vprintf` for printing error message; + * it prints to standard error (rather than standard + * output) and, unless `fmt` starts with "usage: " + * and unless `argv0` (global `char *`), prefixes + * the output with `"%s: ", argv0`; additionally, if + * `fmt` ends with ':', the output is suffixed with + * `" %s\n", strerror(errno)`, if `fmt` ends with + * neither ':' nor '\n', the outpt is suffixed with + * `\n` + * + * This function will exit the process with the + * value `libsimple_default_failure_exit` + * + * NB! This function uses `strerror` which is not + * thread-safe + * + * @param fmt The format string + * @param ... The format argument + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2), __noreturn__))) static inline void libsimple_eprintf(const char *__fmt, ...) diff --git a/libsimple/pvalloc.h b/libsimple/pvalloc.h index dfd7b31..78deb1a 100644 --- a/libsimple/pvalloc.h +++ b/libsimple/pvalloc.h @@ -1,10 +1,26 @@ /* See LICENSE file for copyright and license details. */ -/* - * The alignment will be the page size. - * The allocation size is rounded up to the next multiple of the alignment. - */ +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void *libsimple_vpvallocn(size_t __n, va_list __ap) { return libsimple_vpvalloczn(0, __n, __ap); } @@ -12,6 +28,21 @@ static inline void *libsimple_vpvallocn(size_t __n, va_list __ap) # define vpvallocn libsimple_vpvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void *libsimple_pvalloc(size_t __n) { return libsimple_pvallocz(0, __n); } @@ -19,6 +50,27 @@ static inline void *libsimple_pvalloc(size_t __n) # define pvalloc libsimple_pvalloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_pvallocn(size_t __n, ... /*, (size_t)0 */) @@ -32,6 +84,25 @@ libsimple_pvallocn(size_t __n, ... /*, (size_t)0 */) # define pvallocn libsimple_pvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_enpvalloc(int __status, size_t __n) { return libsimple_enpvallocz(__status, 0, __n); } @@ -39,6 +110,30 @@ static inline void *libsimple_enpvalloc(int __status, size_t __n) # define enpvalloc libsimple_enpvalloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments except `status`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envpvallocn(int __status, size_t __n, va_list __ap) { return libsimple_envpvalloczn(__status, 0, __n, __ap); } @@ -46,6 +141,30 @@ static inline void *libsimple_envpvallocn(int __status, size_t __n, va_list __ap # define envpvallocn libsimple_envpvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments except `status`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enpvallocn(int __status, size_t __n, ... /*, (size_t)0 */) @@ -59,6 +178,24 @@ libsimple_enpvallocn(int __status, size_t __n, ... /*, (size_t)0 */) # define enpvallocn libsimple_enpvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_epvalloc(size_t __n) { return libsimple_enpvalloc(libsimple_default_failure_exit, __n); } @@ -66,6 +203,29 @@ static inline void *libsimple_epvalloc(size_t __n) # define epvalloc libsimple_epvalloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evpvallocn(size_t __n, va_list __ap) { return libsimple_envpvallocn(libsimple_default_failure_exit, __n, __ap); } @@ -73,6 +233,29 @@ static inline void *libsimple_evpvallocn(size_t __n, va_list __ap) # define evpvallocn libsimple_evpvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_epvallocn(size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/pvallocz.h b/libsimple/pvallocz.h index 2fc628d..7821991 100644 --- a/libsimple/pvallocz.h +++ b/libsimple/pvallocz.h @@ -1,10 +1,27 @@ /* See LICENSE file for copyright and license details. */ -/* - * The alignment will be the page size. - * The allocation size is rounded up to the next multiple of the alignment. - */ +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_vpvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]pvalloc[z]n) */ @@ -19,6 +36,22 @@ libsimple_vpvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]pva # define vpvalloczn libsimple_vpvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__))) static inline void * libsimple_pvallocz(int __clear, size_t __n) /* TODO test (pvalloc[z]) */ @@ -33,6 +66,28 @@ libsimple_pvallocz(int __clear, size_t __n) /* TODO test (pvalloc[z]) */ # define pvallocz libsimple_pvallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_pvalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) @@ -46,6 +101,26 @@ libsimple_pvalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) # define pvalloczn libsimple_pvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enpvallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]pvalloc[z]) */ @@ -60,6 +135,32 @@ libsimple_enpvallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]pv # define enpvallocz libsimple_enpvallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `status` and + * `clear`, up to the first 0, will be used as the number + * of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envpvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* TODO test (e[n][v]pvalloc[z]n) */ @@ -75,6 +176,32 @@ libsimple_envpvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* T # define envpvalloczn libsimple_envpvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `status` and + * `clear`, up to the first 0, will be used as the number + * of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_enpvalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) @@ -88,6 +215,25 @@ libsimple_enpvalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 * # define enpvalloczn libsimple_enpvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_epvallocz(int __clear, size_t __n) { return libsimple_enpvallocz(libsimple_default_failure_exit, __clear, __n); } @@ -95,6 +241,30 @@ static inline void *libsimple_epvallocz(int __clear, size_t __n) # define epvallocz libsimple_epvallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evpvalloczn(int __clear, size_t __n, va_list __ap) { return libsimple_envpvalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } @@ -102,6 +272,30 @@ static inline void *libsimple_evpvalloczn(int __clear, size_t __n, va_list __ap) # define evpvalloczn libsimple_evpvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * The allocation size is rounded up to the next multiple + * of the page size (the alignment) + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size, + * rounded up to the next multiple of the page size, + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_epvalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/valloc.h b/libsimple/valloc.h index 6f9d57b..c0fcd03 100644 --- a/libsimple/valloc.h +++ b/libsimple/valloc.h @@ -1,9 +1,22 @@ /* See LICENSE file for copyright and license details. */ -/* - * The alignment will be the page size. - */ +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * @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 A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void *libsimple_vvallocn(size_t __n, va_list __ap) { return libsimple_vvalloczn(0, __n, __ap); } @@ -11,6 +24,17 @@ static inline void *libsimple_vvallocn(size_t __n, va_list __ap) # define vvallocn libsimple_vvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1), __warn_unused_result__))) static inline void *libsimple_valloc(size_t __n) { return libsimple_vallocz(0, __n); } @@ -18,6 +42,23 @@ static inline void *libsimple_valloc(size_t __n) # define valloc libsimple_valloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * @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 A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_vallocn(size_t __n, ... /*, (size_t)0 */) @@ -31,6 +72,21 @@ libsimple_vallocn(size_t __n, ... /*, (size_t)0 */) # define vallocn libsimple_vallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envalloc(int __status, size_t __n) { return libsimple_envallocz(__status, 0, __n); } @@ -38,6 +94,26 @@ static inline void *libsimple_envalloc(int __status, size_t __n) # define envalloc libsimple_envalloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments except `status`, up to the + * first 0, will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_envvallocn(int __status, size_t __n, va_list __ap) { return libsimple_envvalloczn(__status, 0, __n, __ap); } @@ -45,6 +121,26 @@ static inline void *libsimple_envvallocn(int __status, size_t __n, va_list __ap) # define envvallocn libsimple_envvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments except `status`, up to the + * first 0, will be used as the number of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envallocn(int __status, size_t __n, ... /*, (size_t)0 */) @@ -58,6 +154,20 @@ libsimple_envallocn(int __status, size_t __n, ... /*, (size_t)0 */) # define envallocn libsimple_envallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evalloc(size_t __n) { return libsimple_envalloc(libsimple_default_failure_exit, __n); } @@ -65,6 +175,25 @@ static inline void *libsimple_evalloc(size_t __n) # define evalloc libsimple_evalloc #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evvallocn(size_t __n, va_list __ap) { return libsimple_envvallocn(libsimple_default_failure_exit, __n, __ap); } @@ -72,6 +201,25 @@ static inline void *libsimple_evvallocn(size_t __n, va_list __ap) # define evvallocn libsimple_evvallocn #endif + +/** + * Dynamically allocates heap allocated, uninitialised, + * memory with page size alignment + * + * The product of all arguments, up to the first 0, + * will be used as the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_evallocn(size_t __n, ... /*, (size_t)0 */) diff --git a/libsimple/vallocz.h b/libsimple/vallocz.h index 2831cf8..a4765c5 100644 --- a/libsimple/vallocz.h +++ b/libsimple/vallocz.h @@ -1,9 +1,23 @@ /* See LICENSE file for copyright and license details. */ -/* - * The alignment will be the page size. - */ +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_vvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]valloc[z]n) */ @@ -17,6 +31,18 @@ libsimple_vvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]vall # define vvalloczn libsimple_vvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate + * @return A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__))) static inline void * libsimple_vallocz(int __clear, size_t __n) /* TODO test (valloc[z]) */ @@ -30,6 +56,24 @@ libsimple_vallocz(int __clear, size_t __n) /* TODO test (valloc[z]) */ # define vallocz libsimple_vallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment; `NULL` on failure + * @throws EINVAL `n` is 0 + * @throws ENOMEM Could not allocated enough memory + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) static inline void * libsimple_valloczn(int __clear, size_t __n, ... /*, (size_t)0 */) @@ -43,6 +87,22 @@ libsimple_valloczn(int __clear, size_t __n, ... /*, (size_t)0 */) # define valloczn libsimple_valloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]valloc[z]) */ @@ -56,6 +116,28 @@ libsimple_envallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]val # define envallocz libsimple_envallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `status` and + * `clear`, up to the first 0, will be used as the number + * of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* TODO test (e[n][v]valloc[z]n, e[n]vallocn) */ @@ -70,6 +152,28 @@ libsimple_envvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* TO # define envvalloczn libsimple_envvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `status` and + * `clear`, up to the first 0, will be used as the number + * of bytes to allocated + * + * On failure, the `libsimple_enprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_enprintf` for more information + * + * @param status The exit value for the process in case of failure + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_envalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) @@ -83,6 +187,21 @@ libsimple_envalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */ # define envalloczn libsimple_envalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @param n The number of bytes to allocate, the behaviour of + * this function is unspecified for the value 0 + * @return A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evallocz(int __clear, size_t __n) { return libsimple_envallocz(libsimple_default_failure_exit, __clear, __n); } @@ -90,6 +209,26 @@ static inline void *libsimple_evallocz(int __clear, size_t __n) # define evallocz libsimple_evallocz #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void *libsimple_evvalloczn(int __clear, size_t __n, va_list __ap) { return libsimple_envvalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } @@ -97,6 +236,26 @@ static inline void *libsimple_evvalloczn(int __clear, size_t __n, va_list __ap) # define evvalloczn libsimple_evvalloczn #endif + +/** + * Dynamically allocates heap allocated, optionally + * initialised, memory with page size alignment + * + * The product of all arguments except `clear`, up to the + * first 0, will be used as the number of bytes to allocated + * + * On failure, the `libsimple_eprintf` function is called, + * cause the program to print an error message and exit, + * see `libsimple_eprintf` for more information + * + * @param clear Non-zero if the memory should be initialised + * @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 A unique pointer with at least the specified size + * and with page size alignment + */ _LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) static inline void * libsimple_evalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) diff --git a/man/libsimple_aligned_memdup.3 b/man/libsimple_aligned_memdup.3 index 17132ff..6cd287a 100644 --- a/man/libsimple_aligned_memdup.3 +++ b/man/libsimple_aligned_memdup.3 @@ -77,10 +77,10 @@ to indicate the error, and the .BR libsimple_enaligned_memdup (), and .BR libsimple_ealigned_memdup () -functions exit the process group. The +functions exit the process. The .BR libsimple_aligned_memdupa () function cannot fail, however the kernel -can kill the process with a +can kill the thread, and possibly the process, with a .B SIGSEGV signal if the memory cannot be allocated. .PP diff --git a/man/libsimple_enstrdup.3 b/man/libsimple_enstrdup.3 index 512da34..4a2aa4f 100644 --- a/man/libsimple_enstrdup.3 +++ b/man/libsimple_enstrdup.3 @@ -55,10 +55,10 @@ functions return a non-null pointer, on failure the .BR libsimple_enstrdup (), and .BR libsimple_estrdup () -functions exit the process group. The +functions exit the process. The .BR libsimple_strdupa () function cannot fail, however the kernel -can kill the process with a +can kill the thread, and possibly the process, with a .B SIGSEGV signal if the memory cannot be allocated. .PP diff --git a/man/libsimple_enstrndup.3 b/man/libsimple_enstrndup.3 index c761c1c..66272b0 100644 --- a/man/libsimple_enstrndup.3 +++ b/man/libsimple_enstrndup.3 @@ -55,10 +55,10 @@ functions return a non-null pointer, on failure the .BR libsimple_enstrndup (), and .BR libsimple_estrndup () -functions exit the process group. The +functions exit the process. The .BR libsimple_strndupa () function cannot fail, however the kernel -can kill the process with a +can kill the thread, and possibly the process, with a .B SIGSEGV signal if the memory cannot be allocated. .PP diff --git a/man/libsimple_memdup.3 b/man/libsimple_memdup.3 index d9e6d32..e111574 100644 --- a/man/libsimple_memdup.3 +++ b/man/libsimple_memdup.3 @@ -74,10 +74,10 @@ to indicate the error, and the .BR libsimple_enmemdup (), and .BR libsimple_ememdup () -functions exit the process group. The +functions exit the process. The .BR libsimple_memdupa () function cannot fail, however the kernel -can kill the process with a +can kill the thread, and possibly the process, with a .B SIGSEGV signal if the memory cannot be allocated. .PP diff --git a/vweprintf.c b/vweprintf.c index 491763b..96a82a7 100644 --- a/vweprintf.c +++ b/vweprintf.c @@ -20,13 +20,13 @@ libsimple_vweprintf(const char *fmt, va_list ap) va_list ap1; va_list ap2; - if (!argv0 || !strncmp(fmt, "usage: ", strlen("usage: "))) + if (!argv0 || !strncmp(fmt, "usage: ", sizeof("usage: ") - 1)) prefix1 = prefix2 = ""; va_copy(ap1, ap); va_copy(ap2, ap); r = vsnprintf(NULL, 0, fmt, ap1); - if (0 <= r && (size_t)r < SIZE_MAX) { + if (0 <= r && r < 8096) { message = alloca((size_t)r + 1); vsprintf(message, fmt, ap2); } |