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