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