From 181e9c6d5d11cb1e5d36a2777eeb233ad8ed00e5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Oct 2008 18:15:23 +0200 Subject: big pile of updates to match more what happened with libcanberra --- src/malloc.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) (limited to 'src/malloc.c') diff --git a/src/malloc.c b/src/malloc.c index a5171fa..e6a961b 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -1,12 +1,136 @@ +/*** + This file is part of libsydney. + + Copyright 2008 Lennart Poettering + + libsydney is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 2.1 of the + License, or (at your option) any later version. + + libsydney is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libsydney. If not, see + . +***/ + #ifdef HAVE_CONFIG_H #include #endif #include +#include +#include +#include #include "macro.h" #include "malloc.h" +static sa_allocator allocator = { + .malloc = NULL, + .calloc = NULL, + .free = NULL, + .realloc = NULL +}; + +void* sa_malloc(size_t size) { + void *ptr; + + if (size <= 0) + return NULL; + + if (allocator.malloc) + ptr = allocator.malloc(size); + else + ptr = malloc(size); + + if (!ptr) + errno = ENOMEM; + + return ptr; +} + +void sa_free(void *ptr) { + int saved_errno; + + if (!ptr) + return; + + saved_errno = errno; + + if (allocator.free) + allocator.free(ptr); + else + free(ptr); + + errno = saved_errno; +} + +void* sa_malloc0(size_t size) { + void *ptr; + + if (size <= 0) + return NULL; + + if (allocator.calloc) + ptr = allocator.calloc(1, size); + else if (allocator.malloc) { + if ((ptr = allocator.malloc(size))) + memset(ptr, 0, size); + } else + ptr = calloc(1, size); + + if (!ptr) + errno = ENOMEM; + + return ptr; +} + +char *sa_strdup(const char *s) { + char *p; + size_t n_avail; + + if (!s) + return NULL; + + n_avail = strlen(s); + + if (!(p = sa_new(char, n_avail + 1))) + return NULL; + + memcpy(p, s, n_avail); + p[n_avail] = 0; + + return p; +} + +char *sa_strndup(const char *s, size_t n) { + size_t n_avail; + char *p; + + if (!s) + return NULL; + + if (memchr(s, '\0', n)) { + n_avail = strlen(s); + if (n_avail > n) + n_avail = n; + } else + n_avail = n; + + if (!(p = sa_new(char, n_avail + 1))) + return NULL; + + memcpy(p, s, n_avail); + p[n_avail] = 0; + + return p; +} + void* sa_memdup(const void* p, size_t size) { void *r; @@ -18,3 +142,38 @@ void* sa_memdup(const void* p, size_t size) { memcpy(r, p, size); return r; } + +char *sa_sprintf_malloc(const char *format, ...) { + size_t size = 100; + char *c = NULL; + + sa_assert(format); + + for(;;) { + int r; + va_list ap; + + sa_free(c); + + if (!(c = sa_new(char, size))) + return NULL; + + va_start(ap, format); + r = vsnprintf(c, size, format, ap); + va_end(ap); + + c[size-1] = 0; + + if (r > -1 && (size_t) r < size) + return c; + + if (r > -1) /* glibc 2.1 */ + size = (size_t) r+1; + else /* glibc 2.0 */ + size *= 2; + } +} + +void sa_set_allocator(const sa_allocator *a) { + memcpy(&allocator, a, sizeof(allocator)); +} -- cgit