]> git.meshlink.io Git - catta/blob - avahi-common/malloc.c
8c254743d69485cef0016349f1b6a841061beafe
[catta] / avahi-common / malloc.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <stdio.h>
30 #include <unistd.h>
31
32 #include "malloc.h"
33
34 #ifndef va_copy
35 #ifdef __va_copy
36 #define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
37 #else
38 #define va_copy(DEST,SRC) memcpy(&(DEST), &(SRC), sizeof(va_list))
39 #endif
40 #endif
41
42 static const AvahiAllocator *allocator = NULL;
43
44 static void oom(void) AVAHI_GCC_NORETURN;
45
46 static void oom(void) {
47
48     static const char msg[] = "Out of memory, aborting ...\n";
49     const char *n = msg;
50
51     while (strlen(n) > 0) {
52         ssize_t r;
53
54         if ((r = write(2, n, strlen(n))) < 0)
55             break;
56
57         n += r;
58     }
59
60     abort();
61 }
62
63 /* Default implementation for avahi_malloc() */
64 static void* xmalloc(size_t size) {
65     void *p;
66
67     if (size == 0)
68         return NULL;
69
70     if (!(p = malloc(size)))
71         oom();
72
73     return p;
74 }
75
76 /* Default implementation for avahi_realloc() */
77 static void *xrealloc(void *p, size_t size) {
78
79     if (size == 0) {
80         free(p);
81         return NULL;
82     }
83
84     if (!(p = realloc(p, size)))
85         oom();
86
87     return p;
88 }
89
90 /* Default implementation for avahi_calloc() */
91 static void *xcalloc(size_t nmemb, size_t size) {
92     void *p;
93
94     if (size == 0 || nmemb == 0)
95         return NULL;
96
97     if (!(p = calloc(nmemb, size)))
98         oom();
99
100     return p;
101 }
102
103 void *avahi_malloc(size_t size) {
104
105     if (size <= 0)
106         return NULL;
107
108     if (!allocator)
109         return xmalloc(size);
110
111     assert(allocator->malloc);
112     return allocator->malloc(size);
113 }
114
115 void *avahi_malloc0(size_t size) {
116     void *p;
117
118     if (size <= 0)
119         return NULL;
120
121     if (!allocator)
122         return xcalloc(1, size);
123
124     if (allocator->calloc)
125         return allocator->calloc(1, size);
126
127     assert(allocator->malloc);
128     if ((p = allocator->malloc(size)))
129         memset(p, 0, size);
130
131     return p;
132 }
133
134 void avahi_free(void *p) {
135
136     if (!p)
137         return;
138
139     if (!allocator) {
140         free(p);
141         return;
142     }
143
144     assert(allocator->free);
145     allocator->free(p);
146 }
147
148 void *avahi_realloc(void *p, size_t size) {
149
150     if (size == 0) {
151         avahi_free(p);
152         return NULL;
153     }
154
155     if (!allocator)
156         return xrealloc(p, size);
157
158     assert(allocator->realloc);
159     return allocator->realloc(p, size);
160 }
161
162 char *avahi_strdup(const char *s) {
163     char *r;
164     size_t size;
165
166     if (!s)
167         return NULL;
168
169     size = strlen(s);
170     if (!(r = avahi_malloc(size+1)))
171         return NULL;
172
173     memcpy(r, s, size+1);
174     return r;
175 }
176
177 char *avahi_strndup(const char *s, size_t max) {
178     char *r;
179     size_t size;
180     const char *p;
181
182     if (!s)
183         return NULL;
184
185     for (p = s, size = 0;
186          size < max && *p;
187          p++, size++);
188
189     if (!(r = avahi_new(char, size+1)))
190         return NULL;
191
192     memcpy(r, s, size);
193     r[size] = 0;
194     return r;
195 }
196
197 /* Change the allocator */
198 void avahi_set_allocator(const AvahiAllocator *a) {
199     allocator = a;
200 }
201
202 char *avahi_strdup_vprintf(const char *fmt, va_list ap) {
203     size_t len = 80;
204     char *buf;
205
206     assert(fmt);
207
208     if (!(buf = avahi_malloc(len)))
209         return NULL;
210
211     for (;;) {
212         int n;
213         char *nbuf;
214         va_list ap2;
215
216         va_copy (ap2, ap);
217         n = vsnprintf(buf, len, fmt, ap2);
218         va_end (ap2);
219
220         if (n >= 0 && n < (int) len)
221             return buf;
222
223         if (n >= 0)
224             len = n+1;
225         else
226             len *= 2;
227
228         if (!(nbuf = avahi_realloc(buf, len))) {
229             avahi_free(buf);
230             return NULL;
231         }
232
233         buf = nbuf;
234     }
235 }
236
237 char *avahi_strdup_printf(const char *fmt, ... ) {
238     char *s;
239     va_list ap;
240
241     assert(fmt);
242
243     va_start(ap, fmt);
244     s = avahi_strdup_vprintf(fmt, ap);
245     va_end(ap);
246
247     return s;
248 }
249
250 void *avahi_memdup(const void *s, size_t l) {
251     void *p;
252     assert(s);
253
254     if (!(p = avahi_malloc(l)))
255         return NULL;
256
257     memcpy(p, s, l);
258     return p;
259 }