use helper in cmd node
[protos/libecoli.git] / lib / ecoli_malloc.h
index ddf1828..e80c3d9 100644 (file)
@@ -1,38 +1,93 @@
-/*
- * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the University of California, Berkeley nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
+ */
+
+/**
+ * Interface to configure the allocator used by libecoli.
+ * By default, the standard allocation functions from libc are used.
  */
 
 #ifndef ECOLI_MALLOC_
 #define ECOLI_MALLOC_
 
 #include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Function type of malloc, passed to ec_malloc_register().
+ *
+ * The API is the same than malloc(), excepted the file and line
+ * arguments.
+ *
+ * @param size
+ *   The size of the memory area to allocate.
+ * @param file
+ *   The path to the file that invoked the malloc.
+ * @param line
+ *   The line in the file that invoked the malloc.
+ * @return
+ *   A pointer to the allocated memory area, or NULL on error (errno
+ *   is set).
+ */
+typedef void *(*ec_malloc_t)(size_t size, const char *file, unsigned int line);
+
+/**
+ * Function type of free, passed to ec_malloc_register().
+ *
+ * The API is the same than free(), excepted the file and line
+ * arguments.
+ *
+ * @param ptr
+ *   The pointer to the memory area to be freed.
+ * @param file
+ *   The path to the file that invoked the malloc.
+ * @param line
+ *   The line in the file that invoked the malloc.
+ */
+typedef void (*ec_free_t)(void *ptr, const char *file, unsigned int line);
+
+/**
+ * Function type of realloc, passed to ec_malloc_register().
+ *
+ * The API is the same than realloc(), excepted the file and line
+ * arguments.
+ *
+ * @param ptr
+ *   The pointer to the memory area to be reallocated.
+ * @param file
+ *   The path to the file that invoked the malloc.
+ * @param line
+ *   The line in the file that invoked the malloc.
+ * @return
+ *   A pointer to the allocated memory area, or NULL on error (errno
+ *   is set).
+ */
+typedef void *(*ec_realloc_t)(void *ptr, size_t size, const char *file,
+       unsigned int line);
 
-typedef void *(*ec_malloc_t)(size_t size);
-typedef void (*ec_free_t)(void *ptr);
-typedef void *(*ec_realloc_t)(void *ptr, size_t size);
+/**
+ * Register allocation functions.
+ *
+ * This function can be use to register another allocator
+ * to be used by libecoli. By default, ec_malloc(), ec_free() and
+ * ec_realloc() use the standard libc allocator. Another handler
+ * can be used for debug purposes or when running in a specific
+ * environment.
+ *
+ * This function must be called before ec_init().
+ *
+ * @param usr_malloc
+ *   A user-defined malloc function.
+ * @param usr_free
+ *   A user-defined free function.
+ * @param usr_realloc
+ *   A user-defined realloc function.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
+ */
+int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
+       ec_realloc_t usr_realloc);
 
 struct ec_malloc_handler {
        ec_malloc_t malloc;
@@ -42,71 +97,151 @@ struct ec_malloc_handler {
 
 extern struct ec_malloc_handler ec_malloc_handler;
 
-int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
-       ec_realloc_t usr_realloc);
-
-/* internal */
-void *__ec_malloc(size_t size);
-void __ec_free(void *ptr);
-void *__ec_calloc(size_t nmemb, size_t size);
-void *__ec_realloc(void *ptr, size_t size);
-char *__ec_strdup(const char *s);
-char *__ec_strndup(const char *s, size_t n);
-
-/* we use macros here to ensure the file/line stay correct when
- * debugging the standard malloc with valgrind */
-
-#define ec_malloc(sz) ({                               \
-       void *ret_;                                     \
-       if (ec_malloc_handler.malloc == NULL)           \
-               ret_ = malloc(sz);                      \
-       else                                            \
-               ret_ = __ec_malloc(sz);                 \
-       ret_;                                           \
+/**
+ * Allocate a memory area.
+ *
+ * Like malloc(), ec_malloc() allocates size bytes and returns a pointer
+ * to the allocated memory. The memory is not initialized. The memory is
+ * freed with ec_free().
+ *
+ * @param size
+ *   The size of the area to allocate in bytes.
+ * @return
+ *   The pointer to the allocated memory, or NULL on error (errno is set).
+ */
+#define ec_malloc(size) ({                                             \
+       void *ret_;                                                     \
+       if (ec_malloc_handler.malloc == NULL)                           \
+               ret_ = malloc(size);                                    \
+       else                                                            \
+               ret_ = __ec_malloc(size, __FILE__, __LINE__);           \
+       ret_;                                                           \
        })
 
-#define ec_free(ptr) ({                                        \
-       if (ec_malloc_handler.free == NULL)             \
-               free(ptr);                              \
-       else                                            \
-               __ec_free(ptr);                         \
+/**
+ * Ecoli malloc function.
+ *
+ * Use this function when the macro ec_malloc() cannot be used,
+ * for instance when it is passed as a callback pointer.
+ */
+void *ec_malloc_func(size_t size);
+
+/**
+ * Free a memory area.
+ *
+ * Like free(), ec_free() frees the area pointed by ptr, which must have
+ * been returned by a previous call to ec_malloc() or any other
+ * allocation function of this file.
+ *
+ * @param ptr
+ *   The pointer to the memory area.
+ */
+#define ec_free(ptr) ({                                                        \
+       if (ec_malloc_handler.free == NULL)                             \
+               free(ptr);                                              \
+       else                                                            \
+               __ec_free(ptr, __FILE__, __LINE__);                     \
        })
 
-#define ec_realloc(ptr, sz) ({                         \
-       void *ret_;                                     \
-       if (ec_malloc_handler.realloc == NULL)          \
-               ret_ = realloc(ptr, sz);                \
-       else                                            \
-               ret_ = __ec_realloc(ptr, sz);           \
-       ret_;                                           \
+/**
+ * Ecoli free function.
+ *
+ * Use this function when the macro ec_free() cannot be used,
+ * for instance when it is passed as a callback pointer.
+ */
+void ec_free_func(void *ptr);
+
+/**
+ * Resize an allocated memory area.
+ *
+ * @param ptr
+ *   The pointer to the previously allocated memory area, or NULL.
+ * @param size
+ *   The new size of the memory area.
+ * @return
+ *   A pointer to the newly allocated memory, or NULL if the request
+ *   fails. In that case, the original area is left untouched.
+ */
+#define ec_realloc(ptr, size) ({                                       \
+       void *ret_;                                                     \
+       if (ec_malloc_handler.realloc == NULL)                          \
+               ret_ = realloc(ptr, size);                              \
+       else                                                            \
+               ret_ = __ec_realloc(ptr, size, __FILE__, __LINE__);     \
+       ret_;                                                           \
        })
 
-#define ec_calloc(n, sz) ({                            \
-       void *ret_;                                     \
-       if (ec_malloc_handler.malloc == NULL)           \
-               ret_ = calloc(n, sz);                   \
-       else                                            \
-               ret_ = __ec_calloc(n, sz);              \
-       ret_;                                           \
+/**
+ * Allocate and initialize an array of elements.
+ *
+ * @param n
+ *   The number of elements.
+ * @param size
+ *   The size of each element.
+ * @return
+ *   The pointer to the allocated memory, or NULL on error (errno is set).
+ */
+#define ec_calloc(n, size) ({                                          \
+       void *ret_;                                                     \
+       if (ec_malloc_handler.malloc == NULL)                           \
+               ret_ = calloc(n, size);                                 \
+       else                                                            \
+               ret_ = __ec_calloc(n, size, __FILE__, __LINE__);        \
+       ret_;                                                           \
        })
 
-#define ec_strdup(s) ({                                        \
-       void *ret_;                                     \
-       if (ec_malloc_handler.malloc == NULL)           \
-               ret_ = strdup(s);                       \
-       else                                            \
-               ret_ = __ec_strdup(s);                  \
-       ret_;                                           \
+/**
+ * Duplicate a string.
+ *
+ * Memory for the new string is obtained with ec_malloc(), and can be
+ * freed with ec_free().
+ *
+ * @param s
+ *   The string to be duplicated.
+ * @return
+ *   The pointer to the duplicated string, or NULL on error (errno is set).
+ */
+#define ec_strdup(s) ({                                                        \
+       void *ret_;                                                     \
+       if (ec_malloc_handler.malloc == NULL)                           \
+               ret_ = strdup(s);                                       \
+       else                                                            \
+               ret_ = __ec_strdup(s, __FILE__, __LINE__);              \
+       ret_;                                                           \
        })
 
-#define ec_strndup(s, n) ({                            \
-       void *ret_;                                     \
-       if (ec_malloc_handler.malloc == NULL)           \
-               ret_ = strndup(s, n);                   \
-       else                                            \
-               ret_ = __ec_strndup(s, n);              \
-       ret_;                                           \
+/**
+ * Duplicate at most n bytes of a string.
+ *
+ * This function is similar to ec_strdup(), except that it copies at
+ * most n bytes.  If s is longer than n, only n bytes are copied, and a
+ * terminating null byte ('\0') is added.
+ *
+ * @param s
+ *   The string to be duplicated.
+ * @param n
+ *   The maximum length of the new string.
+ * @return
+ *   The pointer to the duplicated string, or NULL on error (errno is set).
+ */
+#define ec_strndup(s, n) ({                                            \
+       void *ret_;                                                     \
+       if (ec_malloc_handler.malloc == NULL)                           \
+               ret_ = strndup(s, n);                                   \
+       else                                                            \
+               ret_ = __ec_strndup(s, n, __FILE__, __LINE__);          \
+       ret_;                                                           \
        })
 
+/* internal */
+void *__ec_malloc(size_t size, const char *file, unsigned int line);
+void __ec_free(void *ptr, const char *file, unsigned int line);
+void *__ec_calloc(size_t nmemb, size_t size, const char *file,
+       unsigned int line);
+void *__ec_realloc(void *ptr, size_t size, const char *file, unsigned int line);
+char *__ec_strdup(const char *s, const char *file, unsigned int line);
+char *__ec_strndup(const char *s, size_t n, const char *file,
+       unsigned int line);
+
 
 #endif