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