source: roaraudio/libroar/memmgr.c @ 6058:713a88b864aa

Last change on this file since 6058:713a88b864aa was 6058:713a88b864aa, checked in by phi, 9 years ago

ignore calls to roar_mm_free() with ptr set to NULL

File size: 11.1 KB
Line 
1//memmgr.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2015
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#ifdef ROAR_USE_MEMMGR
39#define NULL_BUFFER_CONST "RoarAudio"
40static char _libroar_null_buffer[] = NULL_BUFFER_CONST; // A byte sequense >= 8 byte.
41
42static inline void _libroar_null_buffer_check(void) {
43 if ( memcmp(_libroar_null_buffer, NULL_BUFFER_CONST, sizeof(_libroar_null_buffer)) != 0 )
44  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION_GUARD, NULL);
45 memcpy(_libroar_null_buffer, NULL_BUFFER_CONST, sizeof(_libroar_null_buffer));
46}
47#endif
48
49#define _err(x) do { roar_err_set((x)); return NULL; } while (0)
50
51#ifdef ROAR_HAVE_CALLOC
52static void *  __libroar_calloc   (void * userdata, size_t nmemb, size_t size) {
53 void * ret;
54 roar_err_clear_all();
55 ret  = calloc(nmemb, size);
56 roar_err_update();
57 return ret;
58}
59#endif
60#ifdef ROAR_HAVE_MALLOC
61static void *  __libroar_malloc   (void * userdata, size_t size) {
62 void * ret;
63 roar_err_clear_all();
64 ret  = malloc(size);
65 roar_err_update();
66 return ret;
67}
68#endif
69#ifdef ROAR_HAVE_FREE
70static int     __libroar_free     (void * userdata, void * ptr) {
71 free(ptr);
72 return 0;
73}
74#endif
75#ifdef ROAR_HAVE_REALLOC
76static void *  __libroar_realloc  (void * userdata, void * ptr, size_t size) {
77 void * ret;
78 roar_err_clear_all();
79 ret  = realloc(ptr, size);
80 roar_err_update();
81 return ret;
82}
83#endif
84
85static const struct roar_libroar_memmgrapi __memory_default_api = {
86#ifdef ROAR_HAVE_CALLOC
87 .calloc = __libroar_calloc,
88#else
89 .calloc = NULL,
90#endif
91#ifdef ROAR_HAVE_MALLOC
92 .malloc = __libroar_malloc,
93#else
94 .malloc = NULL,
95#endif
96#ifdef ROAR_HAVE_FREE
97 .free = __libroar_free,
98#else
99 .free = NULL,
100#endif
101#ifdef ROAR_HAVE_REALLOC
102 .realloc = __libroar_realloc,
103#else
104 .realloc = NULL,
105#endif
106 .reset = NULL, // not needed
107 .sizeofbuf = NULL, // not supported
108
109 // Not yet supported:
110 .mlock = NULL,
111 .munlock = NULL,
112 .mlockall = NULL,
113 .munlockall = NULL,
114
115 // no need with C API.
116 .userdata = NULL
117};
118
119static const struct roar_libroar_memmgrapi * memory_api = &__memory_default_api;
120
121int    roar_libroar_set_memmgrapi(const struct roar_libroar_memmgrapi * api) {
122 if ( api == NULL )
123  memory_api = &__memory_default_api;
124 memory_api = api;
125 return 0;
126}
127
128#ifdef ROAR_USE_MEMMGR
129int     roar_mm_reset(void) {
130 // currently this does nothing.
131 // we need to free pools and such here later.
132
133 if ( memory_api->reset != NULL )
134  return memory_api->reset(memory_api->userdata);
135 return 0;
136}
137
138ssize_t roar_mm_sizeof(void * buf) {
139 if ( buf == NULL ) {
140  roar_err_set(ROAR_ERROR_FAULT);
141  return -1;
142 }
143
144 if ( buf == _libroar_null_buffer_check )
145  return 0;
146
147 if ( memory_api->sizeofbuf != NULL )
148  return memory_api->sizeofbuf(memory_api->userdata, buf);
149
150 roar_err_set(ROAR_ERROR_NOTSUP);
151 return -1;
152}
153
154void * roar_mm_calloc(size_t nmemb, size_t size) {
155 void * ret;
156
157 if ( nmemb == 0 || size == 0 ) {
158  _libroar_null_buffer_check();
159  return _libroar_null_buffer;
160 }
161
162 if ( memory_api->calloc != NULL ) {
163  return memory_api->calloc(memory_api->userdata, nmemb, size);
164 } else {
165  ret = roar_mm_malloc(nmemb*size);
166  if ( ret == NULL )
167   return NULL;
168
169  memset(ret, 0, nmemb*size);
170
171  return ret;
172 }
173}
174
175void * roar_mm_malloc(size_t size) {
176 if ( size == 0 ) {
177  _libroar_null_buffer_check();
178  return _libroar_null_buffer;
179 }
180
181 if ( memory_api->malloc != NULL ) {
182  return memory_api->malloc(memory_api->userdata, size);
183 } else if ( memory_api->calloc != NULL ) {
184  return roar_mm_calloc(1, size);
185 } else if ( memory_api->realloc != NULL ) {
186  return roar_mm_realloc(NULL, size);
187 } else {
188  _err(ROAR_ERROR_NOSYS);
189 }
190}
191
192int    roar_mm_free(void *ptr) {
193 if ( ptr == NULL )
194  return 0;
195
196 if ( ptr == _libroar_null_buffer ) {
197  _libroar_null_buffer_check();
198  return 0;
199 }
200
201 if ( memory_api->free != NULL ) {
202  return memory_api->free(memory_api->userdata, ptr);
203 } else if ( memory_api->realloc != NULL ) {
204  if ( roar_mm_realloc(ptr, 0) != _libroar_null_buffer )
205   return -1;
206  return 0;
207 } else {
208  roar_err_set(ROAR_ERROR_NOSYS);
209  return -1;
210 }
211}
212
213void * roar_mm_realloc(void *ptr, size_t size) {
214 void * ret;
215 ssize_t len;
216
217 if ( ptr == NULL )
218  return roar_mm_malloc(size);
219
220 if ( size == 0 ) {
221  roar_mm_free(ptr);
222  _libroar_null_buffer_check();
223  return _libroar_null_buffer;
224 }
225
226 if ( memory_api->realloc != NULL ) {
227  return memory_api->realloc(memory_api->userdata, ptr, size);
228 } else {
229  len = roar_mm_sizeof(ptr);
230  if ( len == -1 )
231   return NULL;
232
233  ret = roar_mm_malloc(size);
234  if ( ret == NULL )
235   return NULL;
236
237  memcpy(ret, ptr, len > (ssize_t)size ? size : len);
238
239  return ret;
240 }
241}
242#endif
243
244void * roar_mm_memdup(const void * s, size_t len) {
245 void * ret;
246
247 if ( s == NULL )
248  _err(ROAR_ERROR_FAULT);
249
250#ifdef ROAR_USE_MEMMGR
251 if ( len == 0 ) {
252  _libroar_null_buffer_check();
253  return _libroar_null_buffer;
254 }
255#endif
256
257 ret = roar_mm_malloc(len);
258
259 if ( ret == NULL )
260  return NULL;
261
262 memcpy(ret, s, len);
263
264 return ret;
265}
266
267void roar_mm_free_retvoid(void *ptr) {
268 roar_mm_free(ptr);
269}
270
271void roar_mm_free_noerror(void *ptr) {
272 struct roar_error_state state;
273
274 if ( ptr == NULL )
275  return;
276
277 roar_err_store(&state);
278 roar_mm_free(ptr);
279 roar_err_restore(&state);
280}
281
282#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRDUP)
283char * roar_mm_strdup(const char *s) {
284 void * ret;
285#ifndef ROAR_HAVE_STRDUP
286 ssize_t len;
287#endif
288
289 if ( s == NULL )
290  _err(ROAR_ERROR_FAULT);
291
292#ifdef ROAR_HAVE_STRDUP
293 roar_err_clear_all();
294 ret = strdup(s);
295
296 if ( ret == NULL )
297  roar_err_update();
298#else
299 len = roar_mm_strlen(s);
300 if ( len == -1 )
301  return NULL;
302
303 ret = roar_mm_memdup(s, len+1);
304#endif
305
306 return ret;
307}
308#endif
309
310#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRNDUP)
311char *roar_mm_strndup(const char *s, size_t n) {
312 void * ret;
313#ifndef ROAR_HAVE_STRNDUP
314 ssize_t len;
315#endif
316
317 if ( s == NULL )
318  _err(ROAR_ERROR_FAULT);
319
320#ifdef ROAR_USE_MEMMGR
321 if ( n == 0 ) {
322  _libroar_null_buffer_check();
323  return _libroar_null_buffer;
324 }
325#endif
326
327#ifdef ROAR_HAVE_STRNDUP
328 roar_err_clear_all();
329 ret = strndup(s, n);
330
331 if ( ret == NULL )
332  roar_err_update();
333#else
334 len = roar_mm_strnlen(s, n);
335 if ( len == -1 )
336  return NULL;
337
338 ret = roar_mm_memdup(s, len+1);
339#endif
340
341 return ret;
342}
343#endif
344
345char * roar_mm_strdup2(const char *s, const char *def) {
346 if ( s == NULL )
347  s = def;
348 if ( s == NULL ) {
349  roar_err_clear();
350  return NULL;
351 }
352
353 return roar_mm_strdup(s);
354}
355
356#ifndef ROAR_HAVE_STRLEN
357ssize_t roar_mm_strlen(const char *s) {
358 size_t ret = 0;
359
360 if ( s == NULL ) {
361  roar_err_set(ROAR_ERROR_FAULT);
362  return -1;
363 }
364
365 for (; *s != 0; s++, ret++);
366
367 return ret;
368}
369#endif
370
371ssize_t roar_mm_strnlen(const char *s, size_t maxlen) {
372 size_t ret = 0;
373
374 if ( s == NULL ) {
375  roar_err_set(ROAR_ERROR_FAULT);
376  return -1;
377 }
378
379#ifdef ROAR_HAVE_STRNLEN
380 ret = strnlen(s, maxlen);
381#else
382 for (; ret < maxlen && *s != 0; s++, ret++);
383#endif
384
385 if ( ret == maxlen ) {
386  roar_err_set(ROAR_ERROR_MSGSIZE);
387  return -1;
388 }
389
390 return ret;
391}
392
393
394#ifndef ROAR_HAVE_STRLCPY
395ssize_t roar_mm_strlcpy(char *dst, const char *src, size_t size) {
396 ssize_t len;
397
398 if ( dst == NULL || src == NULL ) {
399  roar_err_set(ROAR_ERROR_FAULT);
400  return -1;
401 }
402
403 if ( size == 0 )
404  return 0;
405
406 len = roar_mm_strlen(src);
407 if ( len == -1 )
408  return -1;
409
410 if ( len < (ssize_t)size ) {
411  memcpy(dst, src, len);
412  dst[len] = 0;
413 } else {
414  memcpy(dst, src, size - 1);
415  dst[size-1] = 0;
416 }
417
418 return len;
419}
420#endif
421
422#ifndef ROAR_HAVE_STRLCAT
423ssize_t roar_mm_strlcat(char *dst, const char *src, size_t size) {
424 ssize_t slen;
425 ssize_t dlen;
426 int err;
427
428 if ( dst == NULL || src == NULL ) {
429  roar_err_set(ROAR_ERROR_FAULT);
430  return -1;
431 }
432
433 if ( size == 0 )
434  return 0;
435
436 slen = roar_mm_strlen(src);
437 if ( slen == -1 )
438  return -1;
439
440 dlen = roar_mm_strnlen(dst, size);
441 err  = roar_error;
442 if ( dlen == -1 && err == ROAR_ERROR_MSGSIZE )
443  dlen = size;
444
445 if ( dlen == -1 )
446  return -1;
447
448 if ( (dlen + slen) < (ssize_t)size ) {
449  memcpy(dst+dlen, src, slen);
450  dst[dlen+slen] = 0;
451 } else if ( dlen != (ssize_t)size ) {
452  memcpy(dst+dlen, src, size-dlen-1);
453  dst[size-1] = 0;
454 }
455
456 return dlen+slen;
457}
458#endif
459
460#ifndef ROAR_HAVE_STRTOK_R
461char * roar_mm_strtok_r(char *str, const char *delim, char **saveptr) {
462 char * next;
463
464 if ( delim == NULL || saveptr == NULL ) {
465  roar_err_set(ROAR_ERROR_FAULT);
466  return NULL;
467 }
468
469 if ( delim[0] == 0 ) {
470  roar_err_set(ROAR_ERROR_NOTSUP);
471  return NULL;
472 }
473
474 if ( delim[1] != 0 ) {
475  roar_err_set(ROAR_ERROR_NOTSUP);
476  return NULL;
477 }
478
479 if ( str != NULL ) {
480  next = str;
481 } else {
482  next = *saveptr;
483 }
484
485 if ( next == NULL ) {
486  roar_err_set(ROAR_ERROR_NODATA);
487  return NULL;
488 }
489
490 *saveptr = strstr(next, delim);
491
492 if ( *saveptr != NULL ) {
493  **saveptr = 0;
494  (*saveptr)++;
495 }
496
497 return next;
498}
499#endif
500
501int roar_mm_strselcmp(const char *s1, const char *s2) {
502 register char a, b;
503
504 if ( s1 == s2 )
505  return 0;
506
507 if ( s1 == NULL || s2 == NULL )
508  return -1;
509
510 for (; ; s1++, s2++) {
511  a = *s1;
512  b = *s2;
513
514  if ( a == '*' ) {
515   s1++;
516   a = *s1;
517   if ( a == 0 ) {
518    if ( b == 0 ) {
519     return 1; // no match! ('*' does not mach no-chars)
520    } else {
521     return 0; // match! (string ends with '*' and something not EOS is in b)
522    }
523   } else {
524    for (; *s2 != 0 && *s2 != a; s2++);
525    if ( a != *s2 )
526     return 1; // no match! (did not find correct char)
527   }
528  } else if ( a == 0 || b == 0 ) {
529   if ( a == b ) {
530    return 0; // match!
531   } else {
532    return 1; // no match! (dffrent length)
533   }
534  } else if ( a != b ) {
535   return 1; // no match! (diffrent chars)
536  }
537 }
538
539 return -1;
540}
541
542ssize_t roar_mm_strseltok(const char *s1, char *s2, char ** tok, size_t toks) {
543 register char a, b;
544 size_t idx = 0;
545
546 if ( s1 == NULL || s2 == NULL )
547  return -1;
548
549 for (; ; s1++, s2++) {
550  a = *s1;
551  b = *s2;
552
553  if ( a == 0 || b == 0 ) {
554   if ( a == b ) {
555    return idx;
556   } else {
557    return -1;
558   }
559  } else if ( a == '*' ) {
560   s1++;
561   a = *s1;
562   if ( idx == toks )
563    return -1;
564
565   tok[idx] = s2;
566   idx++;
567
568   for (; *s2 != 0 && *s2 != a; s2++);
569
570   if ( a == 0 )
571    return idx;
572
573   if ( *s1 == 0 )
574    return -1;
575
576   *s2 = 0;
577  }
578 }
579
580 return -1;
581}
582
583//ll
Note: See TracBrowser for help on using the repository browser.