Home | History | Annotate | Download | only in ldlinux
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2008 H. Peter Anvin - All Rights Reserved
      4  *
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
      8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
      9  *   (at your option) any later version; incorporated herein by reference.
     10  *
     11  * ----------------------------------------------------------------------- */
     12 
     13 /*
     14  * refstr.c
     15  *
     16  * Simple reference-counted strings
     17  */
     18 
     19 #include <stdlib.h>
     20 #include <string.h>
     21 #include <stdio.h>
     22 #include <sys/module.h>
     23 #include "refstr.h"
     24 
     25 /* Allocate space for a refstring of len bytes, plus final null */
     26 /* The final null is inserted in the string; the rest is uninitialized. */
     27 char *refstr_alloc(size_t len)
     28 {
     29     char *r = malloc(sizeof(unsigned int) + len + 1);
     30     if (!r)
     31 	return NULL;
     32     *(unsigned int *)r = 1;
     33     r += sizeof(unsigned int);
     34     r[len] = '\0';
     35     return r;
     36 }
     37 
     38 const char *refstrndup(const char *str, size_t len)
     39 {
     40     char *r;
     41 
     42     if (!str)
     43 	return NULL;
     44 
     45     len = strnlen(str, len);
     46     r = refstr_alloc(len);
     47     if (r)
     48 	memcpy(r, str, len);
     49     return r;
     50 }
     51 
     52 const char *refstrdup(const char *str)
     53 {
     54     char *r;
     55     size_t len;
     56 
     57     if (!str)
     58 	return NULL;
     59 
     60     len = strlen(str);
     61     r = refstr_alloc(len);
     62     if (r)
     63 	memcpy(r, str, len);
     64     return r;
     65 }
     66 
     67 int vrsprintf(const char **bufp, const char *fmt, va_list ap)
     68 {
     69     va_list ap1;
     70     int len;
     71     char *p;
     72 
     73     va_copy(ap1, ap);
     74     len = vsnprintf(NULL, 0, fmt, ap1);
     75     va_end(ap1);
     76 
     77     *bufp = p = refstr_alloc(len);
     78     if (!p)
     79 	return -1;
     80 
     81     return vsnprintf(p, len + 1, fmt, ap);
     82 }
     83 
     84 int rsprintf(const char **bufp, const char *fmt, ...)
     85 {
     86     int rv;
     87     va_list ap;
     88 
     89     va_start(ap, fmt);
     90     rv = vrsprintf(bufp, fmt, ap);
     91     va_end(ap);
     92 
     93     return rv;
     94 }
     95 
     96 void refstr_put(const char *r)
     97 {
     98     unsigned int *ref;
     99 
    100     if (r) {
    101 	ref = (unsigned int *)r - 1;
    102 
    103 	if (!--*ref)
    104 	    free(ref);
    105     }
    106 }
    107