Home | History | Annotate | Download | only in menu
      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 "refstr.h"
     23 
     24 /* Allocate space for a refstring of len bytes, plus final null */
     25 /* The final null is inserted in the string; the rest is uninitialized. */
     26 char *refstr_alloc(size_t len)
     27 {
     28     char *r = malloc(sizeof(unsigned int) + len + 1);
     29     if (!r)
     30 	return NULL;
     31     *(unsigned int *)r = 1;
     32     r += sizeof(unsigned int);
     33     r[len] = '\0';
     34     return r;
     35 }
     36 
     37 const char *refstrndup(const char *str, size_t len)
     38 {
     39     char *r;
     40 
     41     if (!str)
     42 	return NULL;
     43 
     44     len = strnlen(str, len);
     45     r = refstr_alloc(len);
     46     if (r)
     47 	memcpy(r, str, len);
     48     return r;
     49 }
     50 
     51 const char *refstrdup(const char *str)
     52 {
     53     char *r;
     54     size_t len;
     55 
     56     if (!str)
     57 	return NULL;
     58 
     59     len = strlen(str);
     60     r = refstr_alloc(len);
     61     if (r)
     62 	memcpy(r, str, len);
     63     return r;
     64 }
     65 
     66 int vrsprintf(const char **bufp, const char *fmt, va_list ap)
     67 {
     68     va_list ap1;
     69     int len;
     70     char *p;
     71 
     72     va_copy(ap1, ap);
     73     len = vsnprintf(NULL, 0, fmt, ap1);
     74     va_end(ap1);
     75 
     76     *bufp = p = refstr_alloc(len);
     77     if (!p)
     78 	return -1;
     79 
     80     return vsnprintf(p, len + 1, fmt, ap);
     81 }
     82 
     83 int rsprintf(const char **bufp, const char *fmt, ...)
     84 {
     85     int rv;
     86     va_list ap;
     87 
     88     va_start(ap, fmt);
     89     rv = vrsprintf(bufp, fmt, ap);
     90     va_end(ap);
     91 
     92     return rv;
     93 }
     94 
     95 void refstr_put(const char *r)
     96 {
     97     unsigned int *ref;
     98 
     99     if (r) {
    100 	ref = (unsigned int *)r - 1;
    101 
    102 	if (!--*ref)
    103 	    free(ref);
    104     }
    105 }
    106