source: roaraudio/libroar/memmgr.c @ 5921:2fa512f52879

Last change on this file since 5921:2fa512f52879 was 5901:64d1f534671b, checked in by phi, 11 years ago

added roar_mm_free_noerror() and make some use out of it

File size: 11.1 KB
Line 
1//memmgr.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013
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
194 if ( ptr == _libroar_null_buffer ) {
195  _libroar_null_buffer_check();
196  return 0;
197 }
198
199 if ( memory_api->free != NULL ) {
200  return memory_api->free(memory_api->userdata, ptr);
201 } else if ( memory_api->realloc != NULL ) {
202  if ( roar_mm_realloc(ptr, 0) != _libroar_null_buffer )
203   return -1;
204  return 0;
205 } else {
206  roar_err_set(ROAR_ERROR_NOSYS);
207  return -1;
208 }
209}
210
211void * roar_mm_realloc(void *ptr, size_t size) {
212 void * ret;
213 ssize_t len;
214
215 if ( ptr == NULL )
216  return roar_mm_malloc(size);
217
218 if ( size == 0 ) {
219  roar_mm_free(ptr);
220  _libroar_null_buffer_check();
221  return _libroar_null_buffer;
222 }
223
224 if ( memory_api->realloc != NULL ) {
225  return memory_api->realloc(memory_api->userdata, ptr, size);
226 } else {
227  len = roar_mm_sizeof(ptr);
228  if ( len == -1 )
229   return NULL;
230
231  ret = roar_mm_malloc(size);
232  if ( ret == NULL )
233   return NULL;
234
235  memcpy(ret, ptr, len > (ssize_t)size ? size : len);
236
237  return ret;
238 }
239}
240#endif
241
242void * roar_mm_memdup(const void * s, size_t len) {
243 void * ret;
244
245 if ( s == NULL )
246  _err(ROAR_ERROR_FAULT);
247
248#ifdef ROAR_USE_MEMMGR
249 if ( len == 0 ) {
250  _libroar_null_buffer_check();
251  return _libroar_null_buffer;
252 }
253#endif
254
255 ret = roar_mm_malloc(len);
256
257 if ( ret == NULL )
258  return NULL;
259
260 memcpy(ret, s, len);
261
262 return ret;
263}
264
265void roar_mm_free_retvoid(void *ptr) {
266 roar_mm_free(ptr);
267}
268
269void roar_mm_free_noerror(void *ptr) {
270 struct roar_error_state state;
271
272 if ( ptr == NULL )
273  return;
274
275 roar_err_store(&state);
276 roar_mm_free(ptr);
277 roar_err_restore(&state);
278}
279
280#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRDUP)
281char * roar_mm_strdup(const char *s) {
282 void * ret;
283#ifndef ROAR_HAVE_STRDUP
284 ssize_t len;
285#endif
286
287 if ( s == NULL )
288  _err(ROAR_ERROR_FAULT);
289
290#ifdef ROAR_HAVE_STRDUP
291 roar_err_clear_all();
292 ret = strdup(s);
293
294 if ( ret == NULL )
295  roar_err_update();
296#else
297 len = roar_mm_strlen(s);
298 if ( len == -1 )
299  return NULL;
300
301 ret = roar_mm_memdup(s, len+1);
302#endif
303
304 return ret;
305}
306#endif
307
308#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRNDUP)
309char *roar_mm_strndup(const char *s, size_t n) {
310 void * ret;
311#ifndef ROAR_HAVE_STRNDUP
312 ssize_t len;
313#endif
314
315 if ( s == NULL )
316  _err(ROAR_ERROR_FAULT);
317
318#ifdef ROAR_USE_MEMMGR
319 if ( n == 0 ) {
320  _libroar_null_buffer_check();
321  return _libroar_null_buffer;
322 }
323#endif
324
325#ifdef ROAR_HAVE_STRNDUP
326 roar_err_clear_all();
327 ret = strndup(s, n);
328
329 if ( ret == NULL )
330  roar_err_update();
331#else
332 len = roar_mm_strnlen(s, n);
333 if ( len == -1 )
334  return NULL;
335
336 ret = roar_mm_memdup(s, len+1);
337#endif
338
339 return ret;
340}
341#endif
342
343char * roar_mm_strdup2(const char *s, const char *def) {
344 if ( s == NULL )
345  s = def;
346 if ( s == NULL ) {
347  roar_err_clear();
348  return NULL;
349 }
350
351 return roar_mm_strdup(s);
352}
353
354#ifndef ROAR_HAVE_STRLEN
355ssize_t roar_mm_strlen(const char *s) {
356 size_t ret = 0;
357
358 if ( s == NULL ) {
359  roar_err_set(ROAR_ERROR_FAULT);
360  return -1;
361 }
362
363 for (; *s != 0; s++, ret++);
364
365 return ret;
366}
367#endif
368
369ssize_t roar_mm_strnlen(const char *s, size_t maxlen) {
370 size_t ret = 0;
371
372 if ( s == NULL ) {
373  roar_err_set(ROAR_ERROR_FAULT);
374  return -1;
375 }
376
377#ifdef ROAR_HAVE_STRNLEN
378 ret = strnlen(s, maxlen);
379#else
380 for (; ret < maxlen && *s != 0; s++, ret++);
381#endif
382
383 if ( ret == maxlen ) {
384  roar_err_set(ROAR_ERROR_MSGSIZE);
385  return -1;
386 }
387
388 return ret;
389}
390
391
392#ifndef ROAR_HAVE_STRLCPY
393ssize_t roar_mm_strlcpy(char *dst, const char *src, size_t size) {
394 ssize_t len;
395
396 if ( dst == NULL || src == NULL ) {
397  roar_err_set(ROAR_ERROR_FAULT);
398  return -1;
399 }
400
401 if ( size == 0 )
402  return 0;
403
404 len = roar_mm_strlen(src);
405 if ( len == -1 )
406  return -1;
407
408 if ( len < (ssize_t)size ) {
409  memcpy(dst, src, len);
410  dst[len] = 0;
411 } else {
412  memcpy(dst, src, size - 1);
413  dst[size-1] = 0;
414 }
415
416 return len;
417}
418#endif
419
420#ifndef ROAR_HAVE_STRLCAT
421ssize_t roar_mm_strlcat(char *dst, const char *src, size_t size) {
422 ssize_t slen;
423 ssize_t dlen;
424 int err;
425
426 if ( dst == NULL || src == NULL ) {
427  roar_err_set(ROAR_ERROR_FAULT);
428  return -1;
429 }
430
431 if ( size == 0 )
432  return 0;
433
434 slen = roar_mm_strlen(src);
435 if ( slen == -1 )
436  return -1;
437
438 dlen = roar_mm_strnlen(dst, size);
439 err  = roar_error;
440 if ( dlen == -1 && err == ROAR_ERROR_MSGSIZE )
441  dlen = size;
442
443 if ( dlen == -1 )
444  return -1;
445
446 if ( (dlen + slen) < (ssize_t)size ) {
447  memcpy(dst+dlen, src, slen);
448  dst[dlen+slen] = 0;
449 } else if ( dlen != (ssize_t)size ) {
450  memcpy(dst+dlen, src, size-dlen-1);
451  dst[size-1] = 0;
452 }
453
454 return dlen+slen;
455}
456#endif
457
458#ifndef ROAR_HAVE_STRTOK_R
459char * roar_mm_strtok_r(char *str, const char *delim, char **saveptr) {
460 char * next;
461
462 if ( delim == NULL || saveptr == NULL ) {
463  roar_err_set(ROAR_ERROR_FAULT);
464  return NULL;
465 }
466
467 if ( delim[0] == 0 ) {
468  roar_err_set(ROAR_ERROR_NOTSUP);
469  return NULL;
470 }
471
472 if ( delim[1] != 0 ) {
473  roar_err_set(ROAR_ERROR_NOTSUP);
474  return NULL;
475 }
476
477 if ( str != NULL ) {
478  next = str;
479 } else {
480  next = *saveptr;
481 }
482
483 if ( next == NULL ) {
484  roar_err_set(ROAR_ERROR_NODATA);
485  return NULL;
486 }
487
488 *saveptr = strstr(next, delim);
489
490 if ( *saveptr != NULL ) {
491  **saveptr = 0;
492  (*saveptr)++;
493 }
494
495 return next;
496}
497#endif
498
499int roar_mm_strselcmp(const char *s1, const char *s2) {
500 register char a, b;
501
502 if ( s1 == s2 )
503  return 0;
504
505 if ( s1 == NULL || s2 == NULL )
506  return -1;
507
508 for (; ; s1++, s2++) {
509  a = *s1;
510  b = *s2;
511
512  if ( a == '*' ) {
513   s1++;
514   a = *s1;
515   if ( a == 0 ) {
516    if ( b == 0 ) {
517     return 1; // no match! ('*' does not mach no-chars)
518    } else {
519     return 0; // match! (string ends with '*' and something not EOS is in b)
520    }
521   } else {
522    for (; *s2 != 0 && *s2 != a; s2++);
523    if ( a != *s2 )
524     return 1; // no match! (did not find correct char)
525   }
526  } else if ( a == 0 || b == 0 ) {
527   if ( a == b ) {
528    return 0; // match!
529   } else {
530    return 1; // no match! (dffrent length)
531   }
532  } else if ( a != b ) {
533   return 1; // no match! (diffrent chars)
534  }
535 }
536
537 return -1;
538}
539
540ssize_t roar_mm_strseltok(const char *s1, char *s2, char ** tok, size_t toks) {
541 register char a, b;
542 size_t idx = 0;
543
544 if ( s1 == NULL || s2 == NULL )
545  return -1;
546
547 for (; ; s1++, s2++) {
548  a = *s1;
549  b = *s2;
550
551  if ( a == 0 || b == 0 ) {
552   if ( a == b ) {
553    return idx;
554   } else {
555    return -1;
556   }
557  } else if ( a == '*' ) {
558   s1++;
559   a = *s1;
560   if ( idx == toks )
561    return -1;
562
563   tok[idx] = s2;
564   idx++;
565
566   for (; *s2 != 0 && *s2 != a; s2++);
567
568   if ( a == 0 )
569    return idx;
570
571   if ( *s1 == 0 )
572    return -1;
573
574   *s2 = 0;
575  }
576 }
577
578 return -1;
579}
580
581//ll
Note: See TracBrowser for help on using the repository browser.