]> git.meshlink.io Git - catta/blob - avahi-common/malloc.c
* Yeh, maybe we should use the copied value instead of the old one...
[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 static const AvahiAllocator *allocator = NULL;
35
36 static void oom(void) AVAHI_GCC_NORETURN;
37
38 static void oom(void) {
39     
40     static const char msg[] = "Out of memory, aborting ...\n";
41     const char *n = msg;
42
43     while (strlen(n) > 0) {
44         ssize_t r;
45         
46         if ((r = write(2, n, strlen(n))) < 0)
47             break;
48
49         n += r;
50     }
51
52     abort();
53 }
54
55 /* Default implementation for avahi_malloc() */
56 static void* xmalloc(size_t size) {
57     void *p;
58
59     if (size == 0)
60         return NULL;
61
62     if (!(p = malloc(size)))
63         oom();
64
65     return p;
66 }
67
68 /* Default implementation for avahi_realloc() */
69 static void *xrealloc(void *p, size_t size) {
70
71     if (size == 0) {
72         free(p);
73         return NULL;
74     }
75
76     if (!(p = realloc(p, size)))
77         oom();
78
79     return p;
80 }
81
82 /* Default implementation for avahi_calloc() */
83 static void *xcalloc(size_t nmemb, size_t size) {
84     void *p;
85     
86     if (size == 0 || nmemb == 0)
87         return NULL;
88
89     if (!(p = calloc(nmemb, size)))
90         oom();
91
92     return p;
93 }
94
95 void *avahi_malloc(size_t size) {
96
97     if (size <= 0)
98         return NULL;
99     
100     if (!allocator)
101         return xmalloc(size);
102
103     assert(allocator->malloc);
104     return allocator->malloc(size);
105 }
106
107 void *avahi_malloc0(size_t size) {
108     void *p;
109
110     if (size <= 0)
111         return NULL;
112
113     if (!allocator)
114         return xcalloc(1, size);
115
116     if (allocator->calloc)
117         return allocator->calloc(1, size);
118
119     assert(allocator->malloc);
120     if ((p = allocator->malloc(size)))
121         memset(p, 0, size);
122
123     return p;
124 }
125
126 void avahi_free(void *p) {
127
128     if (!p)
129         return;
130     
131     if (!allocator) {
132         free(p);
133         return;
134     }
135
136     assert(allocator->free);
137     allocator->free(p);
138 }
139
140 void *avahi_realloc(void *p, size_t size) {
141
142     if (size == 0) {
143         avahi_free(p);
144         return NULL;
145     }
146
147     if (!allocator)
148         return xrealloc(p, size);
149
150     assert(allocator->realloc);
151     return allocator->realloc(p, size);
152 }
153
154 char *avahi_strdup(const char *s) {
155     char *r;
156     size_t size;
157     
158     if (!s)
159         return NULL;
160
161     size = strlen(s);
162     if (!(r = avahi_malloc(size+1)))
163         return NULL;
164
165     memcpy(r, s, size+1);
166     return r;
167 }
168
169 char *avahi_strndup(const char *s, size_t max) {
170     char *r;
171     size_t size;
172     const char *p;
173     
174     if (!s)
175         return NULL;
176
177     for (p = s, size = 0;
178          size < max && *p;
179          p++, size++);
180     
181     if (!(r = avahi_new(char, size+1)))
182         return NULL;
183
184     memcpy(r, s, size);
185     r[size] = 0;
186     return r;
187 }
188
189 /* Change the allocator */
190 void avahi_set_allocator(const AvahiAllocator *a) {
191     allocator = a;
192 }
193
194 char *avahi_strdup_vprintf(const char *fmt, va_list ap) {
195     size_t len = 80;
196     char *buf;
197     
198     assert(fmt);
199
200     if (!(buf = avahi_malloc(len)))
201         return NULL;
202
203     for (;;) {
204         int n;
205         char *nbuf;
206         va_list ap2;
207
208         va_copy (ap2, ap);
209         
210         n = vsnprintf(buf, len, fmt, ap2);
211
212         va_end (ap2);
213
214         if (n >= 0 && n < (int) len)
215             return buf;
216
217         if (n >= 0)
218             len = n+1;
219         else
220             len *= 2;
221
222         if (!(nbuf = avahi_realloc(buf, len))) {
223             avahi_free(buf);
224             return NULL;
225         }
226
227         buf = nbuf;
228     }
229 }
230
231 char *avahi_strdup_printf(const char *fmt, ... ) {
232     char *s;
233     va_list ap;
234
235     assert(fmt);
236     
237     va_start(ap, fmt);
238     s = avahi_strdup_vprintf(fmt, ap);
239     va_end(ap);
240
241     return s;
242 }
243
244 void *avahi_memdup(const void *s, size_t l) {
245     void *p;
246     assert(s);
247
248     if (!(p = avahi_malloc(l)))
249         return NULL;
250
251     memcpy(p, s, l);
252     return p;
253 }