• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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. */
refstr_alloc(size_t len)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 
refstrndup(const char * str,size_t len)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 
refstrdup(const char * str)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 
vrsprintf(const char ** bufp,const char * fmt,va_list ap)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 
rsprintf(const char ** bufp,const char * fmt,...)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 
refstr_put(const char * r)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