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