changeset 510:21d2c66f3521

core: doxygenize alloc
author David Demelier <markand@malikania.fr>
date Sat, 04 Mar 2023 10:06:07 +0100
parents a11cd7ea3a37
children a1b118127f47
files libmlk-core/mlk/core/alloc.c libmlk-core/mlk/core/alloc.h
diffstat 2 files changed, 179 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-core/mlk/core/alloc.c	Sat Mar 04 08:52:57 2023 +0100
+++ b/libmlk-core/mlk/core/alloc.c	Sat Mar 04 10:06:07 2023 +0100
@@ -134,6 +134,7 @@
 reallocate(void *ptr, size_t n, int zero)
 {
 	assert(ptr);
+	assert(n);
 
 	struct block *b = blockat(ptr);
 	size_t osize = b->n * b->w;
--- a/libmlk-core/mlk/core/alloc.h	Sat Mar 04 08:52:57 2023 +0100
+++ b/libmlk-core/mlk/core/alloc.h	Sat Mar 04 10:06:07 2023 +0100
@@ -48,19 +48,76 @@
  * The structure is allocated using the [flexible array member][fam] to avoid
  * allocating data twice.
  *
- * Example:
+ * ### Example: allocating three ints
+ *
+ * Use the ::mlk_alloc_new function to allocate three ints with uninitialized
+ * memory.
+ *
+ * ```c
+ * int *ptr = mlk_alloc_new(3, sizeof (int));
+ *
+ * ptr[0] = 10;
+ * ptr[1] = 20;
+ * ptr[2] = 30;
+ * ```
+ *
+ * This generates the following blocks in memory.
  *
- * Allocating three ints with `int *ptr = mlk_alloc_new(3, sizeof (int))` will
- * create a block as following:
+ * ```
+ * +-----------------+----------------+------------------------+
+ * | What            | Value          | Description            |
+ * +-----------------+----------------+------------------------+
+ * | size_t          | 3              | Three `int` requested  |
+ * | size_t          | sizeof (int)   | Size of one `int`      |
+ * | unsigned char * | undefined      | Content of user memory |
+ * +-----------------+----------------+------------------------+
+ * ```
+ *
+ * \warning The returned address is the `unsigned char *` so the user must
+ *          never free this address directly.
+ *
+ * If you use ::mlk_alloc_renew, the storage will be expanded/shrinked
+ * automatically without the need to pass the actual size of the array.
+ *
+ * ```c
+ * ptr = mlk_alloc_renew(ptr, 6);
  *
- * | Type                      | Description                 |
- * |---------------------------|-----------------------------|
- * | `size_t` = 3              | Number of items allocated   |
- * | `size_t` = `sizeof (int)` | Size of individual elements |
- * | `unsigned char *`         | `int[3]`                    |
+ * // Now ptr holds 6 ints.
+ * //
+ * // ptr[0], ptr[1], ptr[2] are kept unchanged.
+ * // ptr[3-5] are uninitialized.
+ * ```
+ *
+ * The block now looks like this:
+ *
+ * ```
+ * +-----------------+----------------+------------------------+
+ * | What            | Value          | Description            |
+ * +-----------------+----------------+------------------------+
+ * | size_t          | 6              | Six `int` requested    |
+ * | size_t          | sizeof (int)   | Size of one `int`      |
+ * | unsigned char * | undefined      | Content of user memory |
+ * +-----------------+----------------+------------------------+
+ * ```
  *
- * Finally, calling `mlk_alloc_renew(ptr, 6)` will extend the memory for three
- * more ints.
+ * Finally, free the result using ::mlk_alloc_free, DON'T free the pointer
+ * directly.
+ *
+ * ```c
+ * mlk_alloc_free(ptr);
+ * ```
+ *
+ * ## Custom allocators
+ *
+ * The whole library uses allocators defined in this module when it needs to
+ * allocate data. By default, C standard `malloc`, `realloc` and `free` are
+ * used but they call ::mlk_panic in case of memory exhaustion.
+ *
+ * Those functions can be overridden through the ::mlk_alloc_set function with a
+ * set of functions defined in the structure ::mlk_alloc_funcs.
+ *
+ * When using custom allocators, it is recommended to call ::mlk_alloc_set as
+ * early as possible because it will also set internal libraries to use those.
  *
  * [fam]: https://en.wikipedia.org/wiki/Flexible_array_member
  */
@@ -69,9 +126,39 @@
 
 #include "core.h"
 
+/**
+ * \struct mlk_alloc_funcs
+ * \brief Custom allocator
+ */
 struct mlk_alloc_funcs {
-	void *(*alloc)(size_t);
+	/**
+	 * (read-write)
+	 *
+	 * Allocate the number of bytes uninitialized.
+	 *
+	 * \param size the number of bytes to allocate (always > 0)
+	 * \return a pointer to the allocated memory or NULL on error
+	 */
+	void *(*alloc)(size_t size);
+
+	/**
+	 * (read-write)
+	 *
+	 * Realloc the pointer with the new size.
+	 *
+	 * \param ptr the pointer to reallocate (never NULL)
+	 * \param size the new size (always > 0)
+	 * \return a pointer to the allocated memory or NULL on error
+	 */
 	void *(*realloc)(void *, size_t);
+
+	/**
+	 * (read-write)
+	 *
+	 * Free the pointer memory.
+	 *
+	 * \param ptr the pointer to release
+	 */
 	void (*free)(void *);
 };
 
@@ -85,32 +172,101 @@
 
 MLK_CORE_BEGIN_DECLS
 
+/**
+ * Replace the memory allocators.
+ *
+ * The parameter funcs must be kept alive until the program ends or it is
+ * replaced with a new value.
+ *
+ * \param funcs the new allocator or NULL to re-use the defaults
+ */
 void
-mlk_alloc_set(const struct mlk_alloc_funcs *);
+mlk_alloc_set(const struct mlk_alloc_funcs *funcs);
 
+/**
+ * Allocates a block memory.
+ *
+ * \param n the number of elements to allocate
+ * \param w the size of each individual element
+ * \return whatever the allocator returned
+ */
 void *
-mlk_alloc_new(size_t, size_t);
+mlk_alloc_new(size_t n, size_t w);
 
+/**
+ * \copydoc mlk_alloc_new
+ *
+ * Similar to ::mlk_alloc_new but also ensure the data is zero initialized.
+ */
 void *
-mlk_alloc_new0(size_t, size_t);
+mlk_alloc_new0(size_t n, size_t w);
 
-void *
-mlk_alloc_renew(void *, size_t);
-
+/**
+ * Reallocate a block memory.
+ *
+ * \note In contrast to standard `realloc` function, it is NOT possible to pass
+ *       a NULL pointer in this function because it needs to know the initial
+ *       block memory size.
+ *
+ * \pre ptr != NULL
+ * \pre n > 0
+ * \param ptr the pointer to reallocate
+ * \param n the new size
+ * \return whatever the allocator returned to rearrange the pointer memory
+ */
 void *
-mlk_alloc_renew0(void *, size_t);
+mlk_alloc_renew(void *ptr, size_t n);
 
+/**
+ * \copydoc mlk_alloc_renew
+ *
+ * Similar to ::mlk_alloc_new but also ensure expanded data is zero
+ * initialized.
+ */
 void *
-mlk_alloc_dup(const void *, size_t, size_t);
+mlk_alloc_renew0(void *ptr, size_t n);
 
+/**
+ * Duplicate a memory block.
+ *
+ * \pre ptr != NULL
+ * \param ptr the pointer to copy
+ * \param n the number of elements to allocate
+ * \param w the size of each individual element
+ * \return whatever the allocator returned
+ */
+void *
+mlk_alloc_dup(const void *ptr, size_t n, size_t w);
+
+/**
+ * Duplicate a string.
+ *
+ * \pre src != NULL
+ * \param src the string to duplicate
+ * \return whatever the allocator returned
+ */
 char *
-mlk_alloc_sdup(const char *);
+mlk_alloc_sdup(const char *src);
 
+/**
+ * Duplicate a string using a printf(3) format.
+ *
+ * \pre fmt != NULL
+ * \param fmt the printf(3) format string
+ * \return whatever the allocator returned
+ */
 char *
-mlk_alloc_sdupf(const char *, ...);
+mlk_alloc_sdupf(const char *fmt, ...);
 
+/**
+ * Free resources specified by pointer.
+ *
+ * If pointer is null, function is no-op.
+ *
+ * \param ptr the memory to release (maybe NULL)
+ */
 void
-mlk_alloc_free(void *);
+mlk_alloc_free(void *ptr);
 
 /* alloc_pool functions. */
 void