standardize copyright
[protos/libecoli.git] / lib / 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  * On use this function when the macro ec_malloc() cannot be used.
125  */
126 void *ec_malloc_func(size_t size);
127
128 /**
129  * Free a memory area.
130  *
131  * Like free(), ec_free() frees the area pointed by ptr, which must have
132  * been returned by a previous call to ec_malloc() or any other
133  * allocation function of this file.
134  *
135  * @param ptr
136  *   The pointer to the memory area.
137  */
138 #define ec_free(ptr) ({                                                 \
139         if (ec_malloc_handler.free == NULL)                             \
140                 free(ptr);                                              \
141         else                                                            \
142                 __ec_free(ptr, __FILE__, __LINE__);                     \
143         })
144
145 /**
146  * Ecoli free function.
147  *
148  * On use this function when the macro ec_free() cannot be used.
149  */
150 void ec_free_func(void *ptr);
151
152 /**
153  * Resize an allocated memory area.
154  *
155  * @param ptr
156  *   The pointer to the previously allocated memory area, or NULL.
157  * @param size
158  *   The new size of the memory area.
159  * @return
160  *   A pointer to the newly allocated memory, or NULL if the request
161  *   fails. In that case, the original area is left untouched.
162  */
163 #define ec_realloc(ptr, size) ({                                        \
164         void *ret_;                                                     \
165         if (ec_malloc_handler.realloc == NULL)                          \
166                 ret_ = realloc(ptr, size);                              \
167         else                                                            \
168                 ret_ = __ec_realloc(ptr, size, __FILE__, __LINE__);     \
169         ret_;                                                           \
170         })
171
172 /**
173  * Allocate and initialize an array of elements.
174  *
175  * @param n
176  *   The number of elements.
177  * @param size
178  *   The size of each element.
179  * @return
180  *   The pointer to the allocated memory, or NULL on error (errno is set).
181  */
182 #define ec_calloc(n, size) ({                                           \
183         void *ret_;                                                     \
184         if (ec_malloc_handler.malloc == NULL)                           \
185                 ret_ = calloc(n, size);                                 \
186         else                                                            \
187                 ret_ = __ec_calloc(n, size, __FILE__, __LINE__);        \
188         ret_;                                                           \
189         })
190
191 /**
192  * Duplicate a string.
193  *
194  * Memory for the new string is obtained with ec_malloc(), and can be
195  * freed with ec_free().
196  *
197  * @param s
198  *   The string to be duplicated.
199  * @return
200  *   The pointer to the duplicated string, or NULL on error (errno is set).
201  */
202 #define ec_strdup(s) ({                                                 \
203         void *ret_;                                                     \
204         if (ec_malloc_handler.malloc == NULL)                           \
205                 ret_ = strdup(s);                                       \
206         else                                                            \
207                 ret_ = __ec_strdup(s, __FILE__, __LINE__);              \
208         ret_;                                                           \
209         })
210
211 /**
212  * Duplicate at most n bytes of a string.
213  *
214  * This function is similar to ec_strdup(), except that it copies at
215  * most n bytes.  If s is longer than n, only n bytes are copied, and a
216  * terminating null byte ('\0') is added.
217  *
218  * @param s
219  *   The string to be duplicated.
220  * @param n
221  *   The maximum length of the new string.
222  * @return
223  *   The pointer to the duplicated string, or NULL on error (errno is set).
224  */
225 #define ec_strndup(s, n) ({                                             \
226         void *ret_;                                                     \
227         if (ec_malloc_handler.malloc == NULL)                           \
228                 ret_ = strndup(s, n);                                   \
229         else                                                            \
230                 ret_ = __ec_strndup(s, n, __FILE__, __LINE__);          \
231         ret_;                                                           \
232         })
233
234 /* internal */
235 void *__ec_malloc(size_t size, const char *file, unsigned int line);
236 void __ec_free(void *ptr, const char *file, unsigned int line);
237 void *__ec_calloc(size_t nmemb, size_t size, const char *file,
238         unsigned int line);
239 void *__ec_realloc(void *ptr, size_t size, const char *file, unsigned int line);
240 char *__ec_strdup(const char *s, const char *file, unsigned int line);
241 char *__ec_strndup(const char *s, size_t n, const char *file,
242         unsigned int line);
243
244
245 #endif