summaryrefslogtreecommitdiffstats
path: root/src/malloc.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-10-09 18:15:23 +0200
committerLennart Poettering <lennart@poettering.net>2008-10-09 18:15:23 +0200
commit181e9c6d5d11cb1e5d36a2777eeb233ad8ed00e5 (patch)
tree7c280968ce3fded5b325b1480d7f2440ddf93207 /src/malloc.c
parent30a4b516c8d591c11f05df38531f46452d930d2b (diff)
big pile of updates to match more what happened with libcanberra
Diffstat (limited to 'src/malloc.c')
-rw-r--r--src/malloc.c159
1 files changed, 159 insertions, 0 deletions
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
+ <http://www.gnu.org/licenses/>.
+***/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
#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));
+}