alist.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00010  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00011  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00012  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 2001  Nominum, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00024  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00025  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00026  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00029  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /* $Id: alist.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */
00033 
00034 /*! \file */
00035 
00036 #include <config.h>
00037 
00038 #include <stdlib.h>
00039 #include <string.h>
00040 
00041 #include <isccc/alist.h>
00042 #include <isc/assertions.h>
00043 #include <isccc/result.h>
00044 #include <isccc/sexpr.h>
00045 #include <isccc/util.h>
00046 
00047 #define CAR(s)                  (s)->value.as_dottedpair.car
00048 #define CDR(s)                  (s)->value.as_dottedpair.cdr
00049 
00050 #define ALIST_TAG               "*alist*"
00051 #define MAX_INDENT              64
00052 
00053 static char spaces[MAX_INDENT + 1] = 
00054         "                                                                ";
00055 
00056 isccc_sexpr_t *
00057 isccc_alist_create(void)
00058 {
00059         isccc_sexpr_t *alist, *tag;
00060 
00061         tag = isccc_sexpr_fromstring(ALIST_TAG);
00062         if (tag == NULL)
00063                 return (NULL);
00064         alist = isccc_sexpr_cons(tag, NULL);
00065         if (alist == NULL) {
00066                 isccc_sexpr_free(&tag);
00067                 return (NULL);
00068         }
00069 
00070         return (alist);
00071 }
00072 
00073 isc_boolean_t
00074 isccc_alist_alistp(isccc_sexpr_t *alist)
00075 {
00076         isccc_sexpr_t *car;
00077 
00078         if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR)
00079                 return (ISC_FALSE);
00080         car = CAR(alist);
00081         if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING)
00082                 return (ISC_FALSE);
00083         if (strcmp(car->value.as_string, ALIST_TAG) != 0)
00084                 return (ISC_FALSE);
00085         return (ISC_TRUE);
00086 }
00087 
00088 isc_boolean_t
00089 isccc_alist_emptyp(isccc_sexpr_t *alist)
00090 {
00091         REQUIRE(isccc_alist_alistp(alist));
00092 
00093         if (CDR(alist) == NULL)
00094                 return (ISC_TRUE);
00095         return (ISC_FALSE);
00096 }
00097 
00098 isccc_sexpr_t *
00099 isccc_alist_first(isccc_sexpr_t *alist)
00100 {
00101         REQUIRE(isccc_alist_alistp(alist));
00102 
00103         return (CDR(alist));
00104 }
00105 
00106 isccc_sexpr_t *
00107 isccc_alist_assq(isccc_sexpr_t *alist, const char *key)
00108 {
00109         isccc_sexpr_t *car, *caar;
00110 
00111         REQUIRE(isccc_alist_alistp(alist));
00112 
00113         /*
00114          * Skip alist type tag.
00115          */
00116         alist = CDR(alist);
00117 
00118         while (alist != NULL) {
00119                 INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00120                 car = CAR(alist);
00121                 INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00122                 caar = CAR(car);
00123                 if (caar->type == ISCCC_SEXPRTYPE_STRING &&
00124                     strcmp(caar->value.as_string, key) == 0)
00125                         return (car);
00126                 alist = CDR(alist);
00127         }
00128 
00129         return (NULL);
00130 }
00131 
00132 void
00133 isccc_alist_delete(isccc_sexpr_t *alist, const char *key)
00134 {
00135         isccc_sexpr_t *car, *caar, *rest, *prev;
00136 
00137         REQUIRE(isccc_alist_alistp(alist));
00138 
00139         prev = alist;
00140         rest = CDR(alist);
00141         while (rest != NULL) {
00142                 INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00143                 car = CAR(rest);
00144                 INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
00145                 caar = CAR(car);
00146                 if (caar->type == ISCCC_SEXPRTYPE_STRING &&
00147                     strcmp(caar->value.as_string, key) == 0) {
00148                         CDR(prev) = CDR(rest);
00149                         CDR(rest) = NULL;
00150                         isccc_sexpr_free(&rest);
00151                         break;
00152                 }
00153                 prev = rest;
00154                 rest = CDR(rest);
00155         }
00156 }
00157 
00158 isccc_sexpr_t *
00159 isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value)
00160 {
00161         isccc_sexpr_t *kv, *k, *elt;
00162 
00163         kv = isccc_alist_assq(alist, key);
00164         if (kv == NULL) {
00165                 /*
00166                  * New association.
00167                  */
00168                 k = isccc_sexpr_fromstring(key);
00169                 if (k == NULL)
00170                         return (NULL);
00171                 kv = isccc_sexpr_cons(k, value);
00172                 if (kv == NULL) {
00173                         isccc_sexpr_free(&kv);
00174                         return (NULL);
00175                 }
00176                 elt = isccc_sexpr_addtolist(&alist, kv);
00177                 if (elt == NULL) {
00178                         isccc_sexpr_free(&kv);
00179                         return (NULL);
00180                 }
00181         } else {
00182                 /*
00183                  * We've already got an entry for this key.  Replace it.
00184                  */
00185                 isccc_sexpr_free(&CDR(kv));
00186                 CDR(kv) = value;
00187         }
00188 
00189         return (kv);
00190 }
00191 
00192 isccc_sexpr_t *
00193 isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
00194 {
00195         isccc_sexpr_t *v, *kv;
00196 
00197         v = isccc_sexpr_fromstring(str);
00198         if (v == NULL)
00199                 return (NULL);
00200         kv = isccc_alist_define(alist, key, v);
00201         if (kv == NULL)
00202                 isccc_sexpr_free(&v);
00203 
00204         return (kv);
00205 }
00206 
00207 isccc_sexpr_t *
00208 isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r)
00209 {
00210         isccc_sexpr_t *v, *kv;
00211 
00212         v = isccc_sexpr_frombinary(r);
00213         if (v == NULL)
00214                 return (NULL);
00215         kv = isccc_alist_define(alist, key, v);
00216         if (kv == NULL)
00217                 isccc_sexpr_free(&v);
00218 
00219         return (kv);
00220 }
00221 
00222 isccc_sexpr_t *
00223 isccc_alist_lookup(isccc_sexpr_t *alist, const char *key)
00224 {
00225         isccc_sexpr_t *kv;
00226 
00227         kv = isccc_alist_assq(alist, key);
00228         if (kv != NULL)
00229                 return (CDR(kv));
00230         return (NULL);
00231 }
00232 
00233 isc_result_t
00234 isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
00235 {
00236         isccc_sexpr_t *kv, *v;
00237 
00238         kv = isccc_alist_assq(alist, key);
00239         if (kv != NULL) {
00240                 v = CDR(kv);
00241                 if (isccc_sexpr_stringp(v)) {
00242                         if (strp != NULL)
00243                                 *strp = isccc_sexpr_tostring(v);
00244                         return (ISC_R_SUCCESS);
00245                 } else
00246                         return (ISC_R_EXISTS);
00247         }
00248 
00249         return (ISC_R_NOTFOUND);
00250 }
00251 
00252 isc_result_t
00253 isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r)
00254 {
00255         isccc_sexpr_t *kv, *v;
00256 
00257         kv = isccc_alist_assq(alist, key);
00258         if (kv != NULL) {
00259                 v = CDR(kv);
00260                 if (isccc_sexpr_binaryp(v)) {
00261                         if (r != NULL)
00262                                 *r = isccc_sexpr_tobinary(v);
00263                         return (ISC_R_SUCCESS);
00264                 } else
00265                         return (ISC_R_EXISTS);
00266         }
00267 
00268         return (ISC_R_NOTFOUND);
00269 }
00270 
00271 void
00272 isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream)
00273 {
00274         isccc_sexpr_t *elt, *kv, *k, *v;
00275 
00276         if (isccc_alist_alistp(sexpr)) {
00277                 fprintf(stream, "{\n");
00278                 indent += 4;
00279                 for (elt = isccc_alist_first(sexpr);
00280                      elt != NULL;
00281                      elt = CDR(elt)) {
00282                         kv = CAR(elt);
00283                         INSIST(isccc_sexpr_listp(kv));
00284                         k = CAR(kv);
00285                         v = CDR(kv);
00286                         INSIST(isccc_sexpr_stringp(k));
00287                         fprintf(stream, "%.*s%s => ", (int)indent, spaces,
00288                                 isccc_sexpr_tostring(k));
00289                         isccc_alist_prettyprint(v, indent, stream);
00290                         if (CDR(elt) != NULL)
00291                                 fprintf(stream, ",");
00292                         fprintf(stream, "\n");
00293                 }
00294                 indent -= 4;
00295                 fprintf(stream, "%.*s}", (int)indent, spaces);
00296         } else if (isccc_sexpr_listp(sexpr)) {
00297                 fprintf(stream, "(\n");
00298                 indent += 4;
00299                 for (elt = sexpr;
00300                      elt != NULL;
00301                      elt = CDR(elt)) {
00302                         fprintf(stream, "%.*s", (int)indent, spaces);
00303                         isccc_alist_prettyprint(CAR(elt), indent, stream);
00304                         if (CDR(elt) != NULL)
00305                                 fprintf(stream, ",");
00306                         fprintf(stream, "\n");
00307                 }
00308                 indent -= 4;
00309                 fprintf(stream, "%.*s)", (int)indent, spaces);
00310         } else
00311                 isccc_sexpr_print(sexpr, stream);
00312 }

Generated on Tue Apr 28 17:41:06 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha