source: roaraudio/libroar/memmgr.c @ 5823:f9f70dbaa376

Last change on this file since 5823:f9f70dbaa376 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 10.9 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
269#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRDUP)
270char * roar_mm_strdup(const char *s) {
271 void * ret;
272#ifndef ROAR_HAVE_STRDUP
273 ssize_t len;
274#endif
275
276 if ( s == NULL )
277  _err(ROAR_ERROR_FAULT);
278
279#ifdef ROAR_HAVE_STRDUP
280 roar_err_clear_all();
281 ret = strdup(s);
282
283 if ( ret == NULL )
284  roar_err_update();
285#else
286 len = roar_mm_strlen(s);
287 if ( len == -1 )
288  return NULL;
289
290 ret = roar_mm_memdup(s, len+1);
291#endif
292
293 return ret;
294}
295#endif
296
297#if defined(ROAR_USE_MEMMGR) || !defined(ROAR_HAVE_STRNDUP)
298char *roar_mm_strndup(const char *s, size_t n) {
299 void * ret;
300#ifndef ROAR_HAVE_STRNDUP
301 ssize_t len;
302#endif
303
304 if ( s == NULL )
305  _err(ROAR_ERROR_FAULT);
306
307#ifdef ROAR_USE_MEMMGR
308 if ( n == 0 ) {
309  _libroar_null_buffer_check();
310  return _libroar_null_buffer;
311 }
312#endif
313
314#ifdef ROAR_HAVE_STRNDUP
315 roar_err_clear_all();
316 ret = strndup(s, n);
317
318 if ( ret == NULL )
319  roar_err_update();
320#else
321 len = roar_mm_strnlen(s, n);
322 if ( len == -1 )
323  return NULL;
324
325 ret = roar_mm_memdup(s, len+1);
326#endif
327
328 return ret;
329}
330#endif
331
332char * roar_mm_strdup2(const char *s, const char *def) {
333 if ( s == NULL )
334  s = def;
335 if ( s == NULL ) {
336  roar_err_clear();
337  return NULL;
338 }
339
340 return roar_mm_strdup(s);
341}
342
343#ifndef ROAR_HAVE_STRLEN
344ssize_t roar_mm_strlen(const char *s) {
345 size_t ret = 0;
346
347 if ( s == NULL ) {
348  roar_err_set(ROAR_ERROR_FAULT);
349  return -1;
350 }
351
352 for (; *s != 0; s++, ret++);
353
354 return ret;
355}
356#endif
357
358ssize_t roar_mm_strnlen(const char *s, size_t maxlen) {
359 size_t ret = 0;
360
361 if ( s == NULL ) {
362  roar_err_set(ROAR_ERROR_FAULT);
363  return -1;
364 }
365
366#ifdef ROAR_HAVE_STRNLEN
367 ret = strnlen(s, maxlen);
368#else
369 for (; ret < maxlen && *s != 0; s++, ret++);
370#endif
371
372 if ( ret == maxlen ) {
373  roar_err_set(ROAR_ERROR_MSGSIZE);
374  return -1;
375 }
376
377 return ret;
378}
379
380
381#ifndef ROAR_HAVE_STRLCPY
382ssize_t roar_mm_strlcpy(char *dst, const char *src, size_t size) {
383 ssize_t len;
384
385 if ( dst == NULL || src == NULL ) {
386  roar_err_set(ROAR_ERROR_FAULT);
387  return -1;
388 }
389
390 if ( size == 0 )
391  return 0;
392
393 len = roar_mm_strlen(src);
394 if ( len == -1 )
395  return -1;
396
397 if ( len < (ssize_t)size ) {
398  memcpy(dst, src, len);
399  dst[len] = 0;
400 } else {
401  memcpy(dst, src, size - 1);
402  dst[size-1] = 0;
403 }
404
405 return len;
406}
407#endif
408
409#ifndef ROAR_HAVE_STRLCAT
410ssize_t roar_mm_strlcat(char *dst, const char *src, size_t size) {
411 ssize_t slen;
412 ssize_t dlen;
413 int err;
414
415 if ( dst == NULL || src == NULL ) {
416  roar_err_set(ROAR_ERROR_FAULT);
417  return -1;
418 }
419
420 if ( size == 0 )
421  return 0;
422
423 slen = roar_mm_strlen(src);
424 if ( slen == -1 )
425  return -1;
426
427 dlen = roar_mm_strnlen(dst, size);
428 err  = roar_error;
429 if ( dlen == -1 && err == ROAR_ERROR_MSGSIZE )
430  dlen = size;
431
432 if ( dlen == -1 )
433  return -1;
434
435 if ( (dlen + slen) < (ssize_t)size ) {
436  memcpy(dst+dlen, src, slen);
437  dst[dlen+slen] = 0;
438 } else if ( dlen != (ssize_t)size ) {
439  memcpy(dst+dlen, src, size-dlen-1);
440  dst[size-1] = 0;
441 }
442
443 return dlen+slen;
444}
445#endif
446
447#ifndef ROAR_HAVE_STRTOK_R
448char * roar_mm_strtok_r(char *str, const char *delim, char **saveptr) {
449 char * next;
450
451 if ( delim == NULL || saveptr == NULL ) {
452  roar_err_set(ROAR_ERROR_FAULT);
453  return NULL;
454 }
455
456 if ( delim[0] == 0 ) {
457  roar_err_set(ROAR_ERROR_NOTSUP);
458  return NULL;
459 }
460
461 if ( delim[1] != 0 ) {
462  roar_err_set(ROAR_ERROR_NOTSUP);
463  return NULL;
464 }
465
466 if ( str != NULL ) {
467  next = str;
468 } else {
469  next = *saveptr;
470 }
471
472 if ( next == NULL ) {
473  roar_err_set(ROAR_ERROR_NODATA);
474  return NULL;
475 }
476
477 *saveptr = strstr(next, delim);
478
479 if ( *saveptr != NULL ) {
480  **saveptr = 0;
481  (*saveptr)++;
482 }
483
484 return next;
485}
486#endif
487
488int roar_mm_strselcmp(const char *s1, const char *s2) {
489 register char a, b;
490
491 if ( s1 == s2 )
492  return 0;
493
494 if ( s1 == NULL || s2 == NULL )
495  return -1;
496
497 for (; ; s1++, s2++) {
498  a = *s1;
499  b = *s2;
500
501  if ( a == '*' ) {
502   s1++;
503   a = *s1;
504   if ( a == 0 ) {
505    if ( b == 0 ) {
506     return 1; // no match! ('*' does not mach no-chars)
507    } else {
508     return 0; // match! (string ends with '*' and something not EOS is in b)
509    }
510   } else {
511    for (; *s2 != 0 && *s2 != a; s2++);
512    if ( a != *s2 )
513     return 1; // no match! (did not find correct char)
514   }
515  } else if ( a == 0 || b == 0 ) {
516   if ( a == b ) {
517    return 0; // match!
518   } else {
519    return 1; // no match! (dffrent length)
520   }
521  } else if ( a != b ) {
522   return 1; // no match! (diffrent chars)
523  }
524 }
525
526 return -1;
527}
528
529ssize_t roar_mm_strseltok(const char *s1, char *s2, char ** tok, size_t toks) {
530 register char a, b;
531 size_t idx = 0;
532
533 if ( s1 == NULL || s2 == NULL )
534  return -1;
535
536 for (; ; s1++, s2++) {
537  a = *s1;
538  b = *s2;
539
540  if ( a == 0 || b == 0 ) {
541   if ( a == b ) {
542    return idx;
543   } else {
544    return -1;
545   }
546  } else if ( a == '*' ) {
547   s1++;
548   a = *s1;
549   if ( idx == toks )
550    return -1;
551
552   tok[idx] = s2;
553   idx++;
554
555   for (; *s2 != 0 && *s2 != a; s2++);
556
557   if ( a == 0 )
558    return idx;
559
560   if ( *s1 == 0 )
561    return -1;
562
563   *s2 = 0;
564  }
565 }
566
567 return -1;
568}
569
570//ll
Note: See TracBrowser for help on using the repository browser.