hide ec_node structure
[protos/libecoli.git] / include / ecoli_malloc.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
3  */
4
5 /**
6  * @defgroup alloc Allocation
7  * @{
8  *
9  * @brief Helpers to allocate and free memory
10  *
11  * Interface to configure the allocator used by libecoli.
12  * By default, the standard allocation functions from libc are used.
13  */
14
15 #ifndef ECOLI_MALLOC_
16 #define ECOLI_MALLOC_
17
18 #include <sys/types.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 /**
23  * Function type of malloc, passed to ec_malloc_register().
24  *
25  * The API is the same than malloc(), excepted the file and line
26  * arguments.
27  *
28  * @param size
29  *   The size of the memory area to allocate.
30  * @param file
31  *   The path to the file that invoked the malloc.
32  * @param line
33  *   The line in the file that invoked the malloc.
34  * @return
35  *   A pointer to the allocated memory area, or NULL on error (errno
36  *   is set).
37  */
38 typedef void *(*ec_malloc_t)(size_t size, const char *file, unsigned int line);
39
40 /**
41  * Function type of free, passed to ec_malloc_register().
42  *
43  * The API is the same than free(), excepted the file and line
44  * arguments.
45  *
46  * @param ptr
47  *   The pointer to the memory area to be freed.
48  * @param file
49  *   The path to the file that invoked the malloc.
50  * @param line
51  *   The line in the file that invoked the malloc.
52  */
53 typedef void (*ec_free_t)(void *ptr, const char *file, unsigned int line);
54
55 /**
56  * Function type of realloc, passed to ec_malloc_register().
57  *
58  * The API is the same than realloc(), excepted the file and line
59  * arguments.
60  *
61  * @param ptr
62  *   The pointer to the memory area to be reallocated.
63  * @param file
64  *   The path to the file that invoked the malloc.
65  * @param line
66  *   The line in the file that invoked the malloc.
67  * @return
68  *   A pointer to the allocated memory area, or NULL on error (errno
69  *   is set).
70  */
71 typedef void *(*ec_realloc_t)(void *ptr, size_t size, const char *file,
72         unsigned int line);
73
74 /**
75  * Register allocation functions.
76  *
77  * This function can be use to register another allocator
78  * to be used by libecoli. By default, ec_malloc(), ec_free() and
79  * ec_realloc() use the standard libc allocator. Another handler
80  * can be used for debug purposes or when running in a specific
81  * environment.
82  *
83  * This function must be called before ec_init().
84  *
85  * @param usr_malloc
86  *   A user-defined malloc function.
87  * @param usr_free
88  *   A user-defined free function.
89  * @param usr_realloc
90  *   A user-defined realloc function.
91  * @return
92  *   0 on success, or -1 on error (errno is set).
93  */
94 int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
95         ec_realloc_t usr_realloc);
96
97 struct ec_malloc_handler {
98         ec_malloc_t malloc;
99         ec_free_t free;
100         ec_realloc_t realloc;
101 };
102
103 extern struct ec_malloc_handler ec_malloc_handler;
104
105 /**
106  * Allocate a memory area.
107  *
108  * Like malloc(), ec_malloc() allocates size bytes and returns a pointer
109  * to the allocated memory. The memory is not initialized. The memory is
110  * freed with ec_free().
111  *
112  * @param size
113  *   The size of the area to allocate in bytes.
114  * @return
115  *   The pointer to the allocated memory, or NULL on error (errno is set).
116  */
117 #define ec_malloc(size) ({                                              \
118         void *ret_;                                                     \
119         if (ec_malloc_handler.malloc == NULL)                           \
120                 ret_ = malloc(size);                                    \
121         else                                                            \
122                 ret_ = __ec_malloc(size, __FILE__, __LINE__);           \
123         ret_;                                                           \
124         })
125
126 /**
127  * Ecoli malloc function.
128  *
129  * Use this function when the macro ec_malloc() cannot be used,
130  * for instance when it is passed as a callback pointer.
131  */
132 void *ec_malloc_func(size_t size);
133
134 /**
135  * Free a memory area.
136  *
137  * Like free(), ec_free() frees the area pointed by ptr, which must have
138  * been returned by a previous call to ec_malloc() or any other
139  * allocation function of this file.
140  *
141  * @param ptr
142  *   The pointer to the memory area.
143  */
144 #define ec_free(ptr) ({                                                 \
145         if (ec_malloc_handler.free == NULL)                             \
146                 free(ptr);                                              \
147         else                                                            \
148                 __ec_free(ptr, __FILE__, __LINE__);                     \
149         })
150
151 /**
152  * Ecoli free function.
153  *
154  * Use this function when the macro ec_free() cannot be used,
155  * for instance when it is passed as a callback pointer.
156  */
157 void ec_free_func(void *ptr);
158
159 /**
160  * Resize an allocated memory area.
161  *
162  * @param ptr
163  *   The pointer to the previously allocated memory area, or NULL.
164  * @param size
165  *   The new size of the memory area.
166  * @return
167  *   A pointer to the newly allocated memory, or NULL if the request
168  *   fails. In that case, the original area is left untouched.
169  */
170 #define ec_realloc(ptr, size) ({                                        \
171         void *ret_;                                                     \
172         if (ec_malloc_handler.realloc == NULL)                          \
173                 ret_ = realloc(ptr, size);                              \
174         else                                                            \
175                 ret_ = __ec_realloc(ptr, size, __FILE__, __LINE__);     \
176         ret_;                                                           \
177         })
178
179 /**
180  * Ecoli realloc function.
181  *
182  * Use this function when the macro ec_realloc() cannot be used,
183  * for instance when it is passed as a callback pointer.
184  */
185 void ec_realloc_func(void *ptr, size_t size);
186
187 /**
188  * Allocate and initialize an array of elements.
189  *
190  * @param n
191  *   The number of elements.
192  * @param size
193  *   The size of each element.
194  * @return
195  *   The pointer to the allocated memory, or NULL on error (errno is set).
196  */
197 #define ec_calloc(n, size) ({                                           \
198         void *ret_;                                                     \
199         if (ec_malloc_handler.malloc == NULL)                           \
200                 ret_ = calloc(n, size);                                 \
201         else                                                            \
202                 ret_ = __ec_calloc(n, size, __FILE__, __LINE__);        \
203         ret_;                                                           \
204         })
205
206 /**
207  * Duplicate a string.
208  *
209  * Memory for the new string is obtained with ec_malloc(), and can be
210  * freed with ec_free().
211  *
212  * @param s
213  *   The string to be duplicated.
214  * @return
215  *   The pointer to the duplicated string, or NULL on error (errno is set).
216  */
217 #define ec_strdup(s) ({                                                 \
218         void *ret_;                                                     \
219         if (ec_malloc_handler.malloc == NULL)                           \
220                 ret_ = strdup(s);                                       \
221         else                                                            \
222                 ret_ = __ec_strdup(s, __FILE__, __LINE__);              \
223         ret_;                                                           \
224         })
225
226 /**
227  * Duplicate at most n bytes of a string.
228  *
229  * This function is similar to ec_strdup(), except that it copies at
230  * most n bytes.  If s is longer than n, only n bytes are copied, and a
231  * terminating null byte ('\0') is added.
232  *
233  * @param s
234  *   The string to be duplicated.
235  * @param n
236  *   The maximum length of the new string.
237  * @return
238  *   The pointer to the duplicated string, or NULL on error (errno is set).
239  */
240 #define ec_strndup(s, n) ({                                             \
241         void *ret_;                                                     \
242         if (ec_malloc_handler.malloc == NULL)                           \
243                 ret_ = strndup(s, n);                                   \
244         else                                                            \
245                 ret_ = __ec_strndup(s, n, __FILE__, __LINE__);          \
246         ret_;                                                           \
247         })
248
249 /* internal */
250 void *__ec_malloc(size_t size, const char *file, unsigned int line);
251 void __ec_free(void *ptr, const char *file, unsigned int line);
252 void *__ec_calloc(size_t nmemb, size_t size, const char *file,
253         unsigned int line);
254 void *__ec_realloc(void *ptr, size_t size, const char *file, unsigned int line);
255 char *__ec_strdup(const char *s, const char *file, unsigned int line);
256 char *__ec_strndup(const char *s, size_t n, const char *file,
257         unsigned int line);
258
259
260 #endif
261
262 /** @} */