1 /* $Id$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <fnmatch.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 
26 #include "fdm.h"
27 
28 void	*strb_address(struct strb *, const char *);
29 
30 void
strb_create(struct strb ** sbp)31 strb_create(struct strb **sbp)
32 {
33 	*sbp = xcalloc(1, STRBOFFSET);
34 	strb_clear(sbp);
35 }
36 
37 void
strb_clear(struct strb ** sbp)38 strb_clear(struct strb **sbp)
39 {
40 	struct strb	*sb = *sbp;
41 
42 	sb->ent_used = 0;
43 	sb->ent_max = STRBENTRIES;
44 
45 	sb->str_size = STRBBLOCK;
46 	sb->str_used = 0;
47 
48 	sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb));
49 	memset(STRB_BASE(sb), 0, sb->str_size + STRB_ENTSIZE(sb));
50 }
51 
52 void
strb_destroy(struct strb ** sbp)53 strb_destroy(struct strb **sbp)
54 {
55 	xfree(*sbp);
56 	*sbp = NULL;
57 }
58 
59 void
strb_dump(struct strb * sb,const char * prefix,void (* p)(const char *,...))60 strb_dump(struct strb *sb, const char *prefix, void (*p)(const char *, ...))
61 {
62 	struct strbent	*sbe;
63 	u_int		 i;
64 
65 	for (i = 0; i < sb->ent_used; i++) {
66 		sbe = STRB_ENTRY(sb, i);
67 		p("%s: %s: %s", prefix, STRB_KEY(sb, sbe), STRB_VALUE(sb, sbe));
68 	}
69 }
70 
71 void printflike3
strb_add(struct strb ** sbp,const char * key,const char * value,...)72 strb_add(struct strb **sbp, const char *key, const char *value, ...)
73 {
74 	va_list	ap;
75 
76 	va_start(ap, value);
77 	strb_vadd(sbp, key, value, ap);
78 	va_end(ap);
79 }
80 
81 void
strb_vadd(struct strb ** sbp,const char * key,const char * value,va_list ap)82 strb_vadd(struct strb **sbp, const char *key, const char *value, va_list ap)
83 {
84 	struct strb	*sb = *sbp;
85 	size_t		 size, keylen, valuelen;
86 	u_int		 n;
87 	struct strbent	 sbe, *sbep;
88 	va_list		 aq;
89 
90 	keylen = strlen(key) + 1;
91 
92 	va_copy(aq, ap);
93 	valuelen = xvsnprintf(NULL, 0, value, aq) + 1;
94 	va_end(aq);
95 
96 	size = sb->str_size;
97 	while (sb->str_size - sb->str_used < keylen + valuelen) {
98 		if (STRB_SIZE(sb) > SIZE_MAX / 2)
99 			fatalx("size too large");
100 		sb->str_size *= 2;
101 	}
102 	if (size != sb->str_size) {
103 		sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb));
104 		memmove(
105 		    STRB_ENTBASE(sb), STRB_BASE(sb) + size, STRB_ENTSIZE(sb));
106 		memset(STRB_BASE(sb) + size, 0, sb->str_size - size);
107 	}
108 
109 	sbep = strb_address(sb, key);
110 	if (sbep == NULL) {
111 		if (sb->ent_used > sb->ent_max) {
112 			/* Allocate some more entries. */
113 			n = sb->ent_max;
114 
115 			size = STRB_SIZE(sb);
116 			if (sb->ent_max > UINT_MAX / 2)
117 				fatalx("ent_max too large");
118 			sb->ent_max *= 2;
119 			if (STRB_SIZE(sb) < size)
120 				fatalx("size too large");
121 
122 			sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb));
123 
124 			memset(STRB_ENTRY(sb, n), 0, STRB_ENTSIZE(sb) / 2);
125 		}
126 
127 		sbep = STRB_ENTRY(sb, sb->ent_used);
128 		sb->ent_used++;
129 
130 		sbe.key = sb->str_used;
131 		memcpy(STRB_KEY(sb, &sbe), key, keylen);
132 		sb->str_used += keylen;
133 	} else
134 		memcpy(&sbe, sbep, sizeof sbe);
135 	sbe.value = sb->str_used;
136 	xvsnprintf(STRB_VALUE(sb, &sbe), valuelen, value, ap);
137 	sb->str_used += valuelen;
138 
139 	memcpy(sbep, &sbe, sizeof sbe);
140 }
141 
142 void *
strb_address(struct strb * sb,const char * key)143 strb_address(struct strb *sb, const char *key)
144 {
145 	struct strbent	sbe;
146 	u_int		i;
147 
148 	for (i = 0; i < sb->ent_used; i++) {
149 		memcpy(&sbe, STRB_ENTRY(sb, i), sizeof sbe);
150 		if (strcmp(key, STRB_KEY(sb, &sbe)) == 0)
151 			return (STRB_ENTRY(sb, i));
152 	}
153 	return (NULL);
154 }
155 
156 struct strbent *
strb_find(struct strb * sb,const char * key)157 strb_find(struct strb *sb, const char *key)
158 {
159 	static struct strbent	 sbe;
160 	void			*sbep;
161 
162 	sbep = strb_address(sb, key);
163 	if (sbep == NULL)
164 		return (NULL);
165 	memcpy(&sbe, sbep, sizeof sbe);
166 	return (&sbe);
167 }
168 
169 struct strbent *
strb_match(struct strb * sb,const char * patt)170 strb_match(struct strb *sb, const char *patt)
171 {
172 	static struct strbent	 sbe;
173 	u_int			 i;
174 
175 	for (i = 0; i < sb->ent_used; i++) {
176 		memcpy(&sbe, STRB_ENTRY(sb, i), sizeof sbe);
177 		if (fnmatch(patt, STRB_KEY(sb, &sbe), 0) == 0)
178 			return (&sbe);
179 	}
180 	return (NULL);
181 }
182