bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.5.2 / lib / isccc / alist.c
1 /*
2  * Portions Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (C) 2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
12  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * Portions Copyright (C) 2001  Nominum, Inc.
18  *
19  * Permission to use, copy, modify, and/or distribute this software for any
20  * purpose with or without fee is hereby granted, provided that the above
21  * copyright notice and this permission notice appear in all copies.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
24  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
26  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
29  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  */
31
32 /* $Id: alist.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */
33
34 /*! \file */
35
36 #include <config.h>
37
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <isccc/alist.h>
42 #include <isc/assertions.h>
43 #include <isccc/result.h>
44 #include <isccc/sexpr.h>
45 #include <isccc/util.h>
46
47 #define CAR(s)                  (s)->value.as_dottedpair.car
48 #define CDR(s)                  (s)->value.as_dottedpair.cdr
49
50 #define ALIST_TAG               "*alist*"
51 #define MAX_INDENT              64
52
53 static char spaces[MAX_INDENT + 1] = 
54         "                                                                ";
55
56 isccc_sexpr_t *
57 isccc_alist_create(void)
58 {
59         isccc_sexpr_t *alist, *tag;
60
61         tag = isccc_sexpr_fromstring(ALIST_TAG);
62         if (tag == NULL)
63                 return (NULL);
64         alist = isccc_sexpr_cons(tag, NULL);
65         if (alist == NULL) {
66                 isccc_sexpr_free(&tag);
67                 return (NULL);
68         }
69
70         return (alist);
71 }
72
73 isc_boolean_t
74 isccc_alist_alistp(isccc_sexpr_t *alist)
75 {
76         isccc_sexpr_t *car;
77
78         if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR)
79                 return (ISC_FALSE);
80         car = CAR(alist);
81         if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING)
82                 return (ISC_FALSE);
83         if (strcmp(car->value.as_string, ALIST_TAG) != 0)
84                 return (ISC_FALSE);
85         return (ISC_TRUE);
86 }
87
88 isc_boolean_t
89 isccc_alist_emptyp(isccc_sexpr_t *alist)
90 {
91         REQUIRE(isccc_alist_alistp(alist));
92
93         if (CDR(alist) == NULL)
94                 return (ISC_TRUE);
95         return (ISC_FALSE);
96 }
97
98 isccc_sexpr_t *
99 isccc_alist_first(isccc_sexpr_t *alist)
100 {
101         REQUIRE(isccc_alist_alistp(alist));
102
103         return (CDR(alist));
104 }
105
106 isccc_sexpr_t *
107 isccc_alist_assq(isccc_sexpr_t *alist, const char *key)
108 {
109         isccc_sexpr_t *car, *caar;
110
111         REQUIRE(isccc_alist_alistp(alist));
112
113         /*
114          * Skip alist type tag.
115          */
116         alist = CDR(alist);
117
118         while (alist != NULL) {
119                 INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
120                 car = CAR(alist);
121                 INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
122                 caar = CAR(car);
123                 if (caar->type == ISCCC_SEXPRTYPE_STRING &&
124                     strcmp(caar->value.as_string, key) == 0)
125                         return (car);
126                 alist = CDR(alist);
127         }
128
129         return (NULL);
130 }
131
132 void
133 isccc_alist_delete(isccc_sexpr_t *alist, const char *key)
134 {
135         isccc_sexpr_t *car, *caar, *rest, *prev;
136
137         REQUIRE(isccc_alist_alistp(alist));
138
139         prev = alist;
140         rest = CDR(alist);
141         while (rest != NULL) {
142                 INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
143                 car = CAR(rest);
144                 INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
145                 caar = CAR(car);
146                 if (caar->type == ISCCC_SEXPRTYPE_STRING &&
147                     strcmp(caar->value.as_string, key) == 0) {
148                         CDR(prev) = CDR(rest);
149                         CDR(rest) = NULL;
150                         isccc_sexpr_free(&rest);
151                         break;
152                 }
153                 prev = rest;
154                 rest = CDR(rest);
155         }
156 }
157
158 isccc_sexpr_t *
159 isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value)
160 {
161         isccc_sexpr_t *kv, *k, *elt;
162
163         kv = isccc_alist_assq(alist, key);
164         if (kv == NULL) {
165                 /*
166                  * New association.
167                  */
168                 k = isccc_sexpr_fromstring(key);
169                 if (k == NULL)
170                         return (NULL);
171                 kv = isccc_sexpr_cons(k, value);
172                 if (kv == NULL) {
173                         isccc_sexpr_free(&kv);
174                         return (NULL);
175                 }
176                 elt = isccc_sexpr_addtolist(&alist, kv);
177                 if (elt == NULL) {
178                         isccc_sexpr_free(&kv);
179                         return (NULL);
180                 }
181         } else {
182                 /*
183                  * We've already got an entry for this key.  Replace it.
184                  */
185                 isccc_sexpr_free(&CDR(kv));
186                 CDR(kv) = value;
187         }
188
189         return (kv);
190 }
191
192 isccc_sexpr_t *
193 isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
194 {
195         isccc_sexpr_t *v, *kv;
196
197         v = isccc_sexpr_fromstring(str);
198         if (v == NULL)
199                 return (NULL);
200         kv = isccc_alist_define(alist, key, v);
201         if (kv == NULL)
202                 isccc_sexpr_free(&v);
203
204         return (kv);
205 }
206
207 isccc_sexpr_t *
208 isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r)
209 {
210         isccc_sexpr_t *v, *kv;
211
212         v = isccc_sexpr_frombinary(r);
213         if (v == NULL)
214                 return (NULL);
215         kv = isccc_alist_define(alist, key, v);
216         if (kv == NULL)
217                 isccc_sexpr_free(&v);
218
219         return (kv);
220 }
221
222 isccc_sexpr_t *
223 isccc_alist_lookup(isccc_sexpr_t *alist, const char *key)
224 {
225         isccc_sexpr_t *kv;
226
227         kv = isccc_alist_assq(alist, key);
228         if (kv != NULL)
229                 return (CDR(kv));
230         return (NULL);
231 }
232
233 isc_result_t
234 isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
235 {
236         isccc_sexpr_t *kv, *v;
237
238         kv = isccc_alist_assq(alist, key);
239         if (kv != NULL) {
240                 v = CDR(kv);
241                 if (isccc_sexpr_stringp(v)) {
242                         if (strp != NULL)
243                                 *strp = isccc_sexpr_tostring(v);
244                         return (ISC_R_SUCCESS);
245                 } else
246                         return (ISC_R_EXISTS);
247         }
248
249         return (ISC_R_NOTFOUND);
250 }
251
252 isc_result_t
253 isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r)
254 {
255         isccc_sexpr_t *kv, *v;
256
257         kv = isccc_alist_assq(alist, key);
258         if (kv != NULL) {
259                 v = CDR(kv);
260                 if (isccc_sexpr_binaryp(v)) {
261                         if (r != NULL)
262                                 *r = isccc_sexpr_tobinary(v);
263                         return (ISC_R_SUCCESS);
264                 } else
265                         return (ISC_R_EXISTS);
266         }
267
268         return (ISC_R_NOTFOUND);
269 }
270
271 void
272 isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream)
273 {
274         isccc_sexpr_t *elt, *kv, *k, *v;
275
276         if (isccc_alist_alistp(sexpr)) {
277                 fprintf(stream, "{\n");
278                 indent += 4;
279                 for (elt = isccc_alist_first(sexpr);
280                      elt != NULL;
281                      elt = CDR(elt)) {
282                         kv = CAR(elt);
283                         INSIST(isccc_sexpr_listp(kv));
284                         k = CAR(kv);
285                         v = CDR(kv);
286                         INSIST(isccc_sexpr_stringp(k));
287                         fprintf(stream, "%.*s%s => ", (int)indent, spaces,
288                                 isccc_sexpr_tostring(k));
289                         isccc_alist_prettyprint(v, indent, stream);
290                         if (CDR(elt) != NULL)
291                                 fprintf(stream, ",");
292                         fprintf(stream, "\n");
293                 }
294                 indent -= 4;
295                 fprintf(stream, "%.*s}", (int)indent, spaces);
296         } else if (isccc_sexpr_listp(sexpr)) {
297                 fprintf(stream, "(\n");
298                 indent += 4;
299                 for (elt = sexpr;
300                      elt != NULL;
301                      elt = CDR(elt)) {
302                         fprintf(stream, "%.*s", (int)indent, spaces);
303                         isccc_alist_prettyprint(CAR(elt), indent, stream);
304                         if (CDR(elt) != NULL)
305                                 fprintf(stream, ",");
306                         fprintf(stream, "\n");
307                 }
308                 indent -= 4;
309                 fprintf(stream, "%.*s)", (int)indent, spaces);
310         } else
311                 isccc_sexpr_print(sexpr, stream);
312 }