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