748601ab6a80a696de670828f0d8a9498d991481
[protos/libecoli.git] / lib / ecoli_malloc.h
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /**
29  * Interface to configure the allocator used by libecoli.
30  * By default, the standard allocation functions from libc are used.
31  */
32
33 #ifndef ECOLI_MALLOC_
34 #define ECOLI_MALLOC_
35
36 #include <sys/types.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 /**
41  * Function type of malloc, passed to ec_malloc_register().
42  *
43  * The API is the same than malloc(), excepted the file and line
44  * arguments.
45  *
46  * @param size
47  *   The size of the memory area to allocate.
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  * @return
53  *   A pointer to the allocated memory area, or NULL on error (errno
54  *   is set).
55  */
56 typedef void *(*ec_malloc_t)(size_t size, const char *file, unsigned int line);
57
58 /**
59  * Function type of free, passed to ec_malloc_register().
60  *
61  * The API is the same than free(), excepted the file and line
62  * arguments.
63  *
64  * @param ptr
65  *   The pointer to the memory area to be freed.
66  * @param file
67  *   The path to the file that invoked the malloc.
68  * @param line
69  *   The line in the file that invoked the malloc.
70  */
71 typedef void (*ec_free_t)(void *ptr, const char *file, unsigned int line);
72
73 /**
74  * Function type of realloc, passed to ec_malloc_register().
75  *
76  * The API is the same than realloc(), excepted the file and line
77  * arguments.
78  *
79  * @param ptr
80  *   The pointer to the memory area to be reallocated.
81  * @param file
82  *   The path to the file that invoked the malloc.
83  * @param line
84  *   The line in the file that invoked the malloc.
85  * @return
86  *   A pointer to the allocated memory area, or NULL on error (errno
87  *   is set).
88  */
89 typedef void *(*ec_realloc_t)(void *ptr, size_t size, const char *file,
90         unsigned int line);
91
92 /**
93  * Register allocation functions.
94  *
95  * This function can be use to register another allocator
96  * to be used by libecoli. By default, ec_malloc(), ec_free() and
97  * ec_realloc() use the standard libc allocator. Another handler
98  * can be used for debug purposes or when running in a specific
99  * environment.
100  *
101  * This function must be called before ec_init().
102  *
103  * @param usr_malloc
104  *   A user-defined malloc function.
105  * @param usr_free
106  *   A user-defined free function.
107  * @param usr_realloc
108  *   A user-defined realloc function.
109  * @return
110  *   0 on success, or -1 on error (errno is set).
111  */
112 int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
113         ec_realloc_t usr_realloc);
114
115 struct ec_malloc_handler {
116         ec_malloc_t malloc;
117         ec_free_t free;
118         ec_realloc_t realloc;
119 };
120
121 extern struct ec_malloc_handler ec_malloc_handler;
122
123 /**
124  * Allocate a memory area.
125  *
126  * Like malloc(), ec_malloc() allocates size bytes and returns a pointer
127  * to the allocated memory. The memory is not initialized. The memory is
128  * freed with ec_free().
129  *
130  * @param size
131  *   The size of the area to allocate in bytes.
132  * @return
133  *   The pointer to the allocated memory, or NULL on error (errno is set).
134  */
135 #define ec_malloc(size) ({                                              \
136         void *ret_;                                                     \
137         if (ec_malloc_handler.malloc == NULL)                           \
138                 ret_ = malloc(size);                                    \
139         else                                                            \
140                 ret_ = __ec_malloc(size, __FILE__, __LINE__);           \
141         ret_;                                                           \
142         })
143
144 /**
145  * Ecoli malloc function.
146  *
147  * On use this function when the macro ec_malloc() cannot be used.
148  */
149 void *ec_malloc_func(size_t size);
150
151 /**
152  * Free a memory area.
153  *
154  * Like free(), ec_free() frees the area pointed by ptr, which must have
155  * been returned by a previous call to ec_malloc() or any other
156  * allocation function of this file.
157  *
158  * @param ptr
159  *   The pointer to the memory area.
160  */
161 #define ec_free(ptr) ({                                                 \
162         if (ec_malloc_handler.free == NULL)                             \
163                 free(ptr);                                              \
164         else                                                            \
165                 __ec_free(ptr, __FILE__, __LINE__);                     \
166         })
167
168 /**
169  * Ecoli free function.
170  *
171  * On use this function when the macro ec_free() cannot be used.
172  */
173 void ec_free_func(void *ptr);
174
175 /**
176  * Resize an allocated memory area.
177  *
178  * @param ptr
179  *   The pointer to the previously allocated memory area, or NULL.
180  * @param size
181  *   The new size of the memory area.
182  * @return
183  *   A pointer to the newly allocated memory, or NULL if the request
184  *   fails. In that case, the original area is left untouched.
185  */
186 #define ec_realloc(ptr, size) ({                                        \
187         void *ret_;                                                     \
188         if (ec_malloc_handler.realloc == NULL)                          \
189                 ret_ = realloc(ptr, size);                              \
190         else                                                            \
191                 ret_ = __ec_realloc(ptr, size, __FILE__, __LINE__);     \
192         ret_;                                                           \
193         })
194
195 /**
196  * Allocate and initialize an array of elements.
197  *
198  * @param n
199  *   The number of elements.
200  * @param size
201  *   The size of each element.
202  * @return
203  *   The pointer to the allocated memory, or NULL on error (errno is set).
204  */
205 #define ec_calloc(n, size) ({                                           \
206         void *ret_;                                                     \
207         if (ec_malloc_handler.malloc == NULL)                           \
208                 ret_ = calloc(n, size);                                 \
209         else                                                            \
210                 ret_ = __ec_calloc(n, size, __FILE__, __LINE__);        \
211         ret_;                                                           \
212         })
213
214 /**
215  * Duplicate a string.
216  *
217  * Memory for the new string is obtained with ec_malloc(), and can be
218  * freed with ec_free().
219  *
220  * @param s
221  *   The string to be duplicated.
222  * @return
223  *   The pointer to the duplicated string, or NULL on error (errno is set).
224  */
225 #define ec_strdup(s) ({                                                 \
226         void *ret_;                                                     \
227         if (ec_malloc_handler.malloc == NULL)                           \
228                 ret_ = strdup(s);                                       \
229         else                                                            \
230                 ret_ = __ec_strdup(s, __FILE__, __LINE__);              \
231         ret_;                                                           \
232         })
233
234 /**
235  * Duplicate at most n bytes of a string.
236  *
237  * This function is similar to ec_strdup(), except that it copies at
238  * most n bytes.  If s is longer than n, only n bytes are copied, and a
239  * terminating null byte ('\0') is added.
240  *
241  * @param s
242  *   The string to be duplicated.
243  * @param n
244  *   The maximum length of the new string.
245  * @return
246  *   The pointer to the duplicated string, or NULL on error (errno is set).
247  */
248 #define ec_strndup(s, n) ({                                             \
249         void *ret_;                                                     \
250         if (ec_malloc_handler.malloc == NULL)                           \
251                 ret_ = strndup(s, n);                                   \
252         else                                                            \
253                 ret_ = __ec_strndup(s, n, __FILE__, __LINE__);          \
254         ret_;                                                           \
255         })
256
257 /* internal */
258 void *__ec_malloc(size_t size, const char *file, unsigned int line);
259 void __ec_free(void *ptr, const char *file, unsigned int line);
260 void *__ec_calloc(size_t nmemb, size_t size, const char *file,
261         unsigned int line);
262 void *__ec_realloc(void *ptr, size_t size, const char *file, unsigned int line);
263 char *__ec_strdup(const char *s, const char *file, unsigned int line);
264 char *__ec_strndup(const char *s, size_t n, const char *file,
265         unsigned int line);
266
267
268 #endif