1135446Strhodes/* 2193149Sdougb * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Portions Copyright (C) 2001 Internet Software Consortium. 4193149Sdougb * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6193149Sdougb * purpose with or without fee is hereby granted, provided that the above 7193149Sdougb * copyright notice and this permission notice appear in all copies. 8193149Sdougb * 9193149Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL 10193149Sdougb * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 11193149Sdougb * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY 12193149Sdougb * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13193149Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14193149Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15193149Sdougb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16193149Sdougb * 17135446Strhodes * Portions Copyright (C) 2001 Nominum, Inc. 18135446Strhodes * 19193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 20135446Strhodes * purpose with or without fee is hereby granted, provided that the above 21135446Strhodes * copyright notice and this permission notice appear in all copies. 22135446Strhodes * 23135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL 24135446Strhodes * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 25135446Strhodes * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY 26135446Strhodes * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27135446Strhodes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28135446Strhodes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29135446Strhodes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30135446Strhodes */ 31135446Strhodes 32234010Sdougb/* $Id: alist.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */ 33135446Strhodes 34170222Sdougb/*! \file */ 35170222Sdougb 36135446Strhodes#include <config.h> 37135446Strhodes 38135446Strhodes#include <stdlib.h> 39135446Strhodes#include <string.h> 40135446Strhodes 41135446Strhodes#include <isccc/alist.h> 42135446Strhodes#include <isc/assertions.h> 43135446Strhodes#include <isccc/result.h> 44135446Strhodes#include <isccc/sexpr.h> 45135446Strhodes#include <isccc/util.h> 46135446Strhodes 47135446Strhodes#define CAR(s) (s)->value.as_dottedpair.car 48135446Strhodes#define CDR(s) (s)->value.as_dottedpair.cdr 49135446Strhodes 50135446Strhodes#define ALIST_TAG "*alist*" 51135446Strhodes#define MAX_INDENT 64 52135446Strhodes 53135446Strhodesstatic char spaces[MAX_INDENT + 1] = 54135446Strhodes " "; 55135446Strhodes 56135446Strhodesisccc_sexpr_t * 57135446Strhodesisccc_alist_create(void) 58135446Strhodes{ 59135446Strhodes isccc_sexpr_t *alist, *tag; 60135446Strhodes 61135446Strhodes tag = isccc_sexpr_fromstring(ALIST_TAG); 62135446Strhodes if (tag == NULL) 63135446Strhodes return (NULL); 64135446Strhodes alist = isccc_sexpr_cons(tag, NULL); 65135446Strhodes if (alist == NULL) { 66135446Strhodes isccc_sexpr_free(&tag); 67135446Strhodes return (NULL); 68135446Strhodes } 69135446Strhodes 70135446Strhodes return (alist); 71135446Strhodes} 72135446Strhodes 73135446Strhodesisc_boolean_t 74135446Strhodesisccc_alist_alistp(isccc_sexpr_t *alist) 75135446Strhodes{ 76135446Strhodes isccc_sexpr_t *car; 77135446Strhodes 78135446Strhodes if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) 79135446Strhodes return (ISC_FALSE); 80135446Strhodes car = CAR(alist); 81135446Strhodes if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING) 82135446Strhodes return (ISC_FALSE); 83135446Strhodes if (strcmp(car->value.as_string, ALIST_TAG) != 0) 84135446Strhodes return (ISC_FALSE); 85135446Strhodes return (ISC_TRUE); 86135446Strhodes} 87135446Strhodes 88135446Strhodesisc_boolean_t 89135446Strhodesisccc_alist_emptyp(isccc_sexpr_t *alist) 90135446Strhodes{ 91135446Strhodes REQUIRE(isccc_alist_alistp(alist)); 92135446Strhodes 93135446Strhodes if (CDR(alist) == NULL) 94135446Strhodes return (ISC_TRUE); 95135446Strhodes return (ISC_FALSE); 96135446Strhodes} 97135446Strhodes 98135446Strhodesisccc_sexpr_t * 99135446Strhodesisccc_alist_first(isccc_sexpr_t *alist) 100135446Strhodes{ 101135446Strhodes REQUIRE(isccc_alist_alistp(alist)); 102135446Strhodes 103135446Strhodes return (CDR(alist)); 104135446Strhodes} 105135446Strhodes 106135446Strhodesisccc_sexpr_t * 107135446Strhodesisccc_alist_assq(isccc_sexpr_t *alist, const char *key) 108135446Strhodes{ 109135446Strhodes isccc_sexpr_t *car, *caar; 110135446Strhodes 111135446Strhodes REQUIRE(isccc_alist_alistp(alist)); 112135446Strhodes 113135446Strhodes /* 114135446Strhodes * Skip alist type tag. 115135446Strhodes */ 116135446Strhodes alist = CDR(alist); 117135446Strhodes 118135446Strhodes while (alist != NULL) { 119135446Strhodes INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); 120135446Strhodes car = CAR(alist); 121135446Strhodes INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); 122135446Strhodes caar = CAR(car); 123135446Strhodes if (caar->type == ISCCC_SEXPRTYPE_STRING && 124135446Strhodes strcmp(caar->value.as_string, key) == 0) 125135446Strhodes return (car); 126135446Strhodes alist = CDR(alist); 127135446Strhodes } 128135446Strhodes 129135446Strhodes return (NULL); 130135446Strhodes} 131135446Strhodes 132135446Strhodesvoid 133135446Strhodesisccc_alist_delete(isccc_sexpr_t *alist, const char *key) 134135446Strhodes{ 135135446Strhodes isccc_sexpr_t *car, *caar, *rest, *prev; 136135446Strhodes 137135446Strhodes REQUIRE(isccc_alist_alistp(alist)); 138135446Strhodes 139135446Strhodes prev = alist; 140135446Strhodes rest = CDR(alist); 141135446Strhodes while (rest != NULL) { 142135446Strhodes INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); 143135446Strhodes car = CAR(rest); 144135446Strhodes INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); 145135446Strhodes caar = CAR(car); 146135446Strhodes if (caar->type == ISCCC_SEXPRTYPE_STRING && 147135446Strhodes strcmp(caar->value.as_string, key) == 0) { 148135446Strhodes CDR(prev) = CDR(rest); 149135446Strhodes CDR(rest) = NULL; 150135446Strhodes isccc_sexpr_free(&rest); 151135446Strhodes break; 152135446Strhodes } 153135446Strhodes prev = rest; 154135446Strhodes rest = CDR(rest); 155135446Strhodes } 156135446Strhodes} 157135446Strhodes 158135446Strhodesisccc_sexpr_t * 159135446Strhodesisccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value) 160135446Strhodes{ 161135446Strhodes isccc_sexpr_t *kv, *k, *elt; 162135446Strhodes 163135446Strhodes kv = isccc_alist_assq(alist, key); 164135446Strhodes if (kv == NULL) { 165135446Strhodes /* 166135446Strhodes * New association. 167135446Strhodes */ 168135446Strhodes k = isccc_sexpr_fromstring(key); 169135446Strhodes if (k == NULL) 170135446Strhodes return (NULL); 171135446Strhodes kv = isccc_sexpr_cons(k, value); 172135446Strhodes if (kv == NULL) { 173135446Strhodes isccc_sexpr_free(&kv); 174135446Strhodes return (NULL); 175135446Strhodes } 176135446Strhodes elt = isccc_sexpr_addtolist(&alist, kv); 177135446Strhodes if (elt == NULL) { 178135446Strhodes isccc_sexpr_free(&kv); 179135446Strhodes return (NULL); 180135446Strhodes } 181135446Strhodes } else { 182135446Strhodes /* 183135446Strhodes * We've already got an entry for this key. Replace it. 184135446Strhodes */ 185135446Strhodes isccc_sexpr_free(&CDR(kv)); 186135446Strhodes CDR(kv) = value; 187135446Strhodes } 188135446Strhodes 189135446Strhodes return (kv); 190135446Strhodes} 191135446Strhodes 192135446Strhodesisccc_sexpr_t * 193135446Strhodesisccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str) 194135446Strhodes{ 195135446Strhodes isccc_sexpr_t *v, *kv; 196135446Strhodes 197135446Strhodes v = isccc_sexpr_fromstring(str); 198135446Strhodes if (v == NULL) 199135446Strhodes return (NULL); 200135446Strhodes kv = isccc_alist_define(alist, key, v); 201135446Strhodes if (kv == NULL) 202135446Strhodes isccc_sexpr_free(&v); 203135446Strhodes 204135446Strhodes return (kv); 205135446Strhodes} 206135446Strhodes 207135446Strhodesisccc_sexpr_t * 208135446Strhodesisccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r) 209135446Strhodes{ 210135446Strhodes isccc_sexpr_t *v, *kv; 211135446Strhodes 212135446Strhodes v = isccc_sexpr_frombinary(r); 213135446Strhodes if (v == NULL) 214135446Strhodes return (NULL); 215135446Strhodes kv = isccc_alist_define(alist, key, v); 216135446Strhodes if (kv == NULL) 217135446Strhodes isccc_sexpr_free(&v); 218135446Strhodes 219135446Strhodes return (kv); 220135446Strhodes} 221135446Strhodes 222135446Strhodesisccc_sexpr_t * 223135446Strhodesisccc_alist_lookup(isccc_sexpr_t *alist, const char *key) 224135446Strhodes{ 225135446Strhodes isccc_sexpr_t *kv; 226135446Strhodes 227135446Strhodes kv = isccc_alist_assq(alist, key); 228135446Strhodes if (kv != NULL) 229135446Strhodes return (CDR(kv)); 230135446Strhodes return (NULL); 231135446Strhodes} 232135446Strhodes 233135446Strhodesisc_result_t 234135446Strhodesisccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp) 235135446Strhodes{ 236135446Strhodes isccc_sexpr_t *kv, *v; 237135446Strhodes 238135446Strhodes kv = isccc_alist_assq(alist, key); 239135446Strhodes if (kv != NULL) { 240135446Strhodes v = CDR(kv); 241135446Strhodes if (isccc_sexpr_stringp(v)) { 242135446Strhodes if (strp != NULL) 243135446Strhodes *strp = isccc_sexpr_tostring(v); 244135446Strhodes return (ISC_R_SUCCESS); 245135446Strhodes } else 246135446Strhodes return (ISC_R_EXISTS); 247135446Strhodes } 248135446Strhodes 249135446Strhodes return (ISC_R_NOTFOUND); 250135446Strhodes} 251135446Strhodes 252135446Strhodesisc_result_t 253135446Strhodesisccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r) 254135446Strhodes{ 255135446Strhodes isccc_sexpr_t *kv, *v; 256135446Strhodes 257135446Strhodes kv = isccc_alist_assq(alist, key); 258135446Strhodes if (kv != NULL) { 259135446Strhodes v = CDR(kv); 260135446Strhodes if (isccc_sexpr_binaryp(v)) { 261135446Strhodes if (r != NULL) 262135446Strhodes *r = isccc_sexpr_tobinary(v); 263135446Strhodes return (ISC_R_SUCCESS); 264135446Strhodes } else 265135446Strhodes return (ISC_R_EXISTS); 266135446Strhodes } 267135446Strhodes 268135446Strhodes return (ISC_R_NOTFOUND); 269135446Strhodes} 270135446Strhodes 271135446Strhodesvoid 272135446Strhodesisccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream) 273135446Strhodes{ 274135446Strhodes isccc_sexpr_t *elt, *kv, *k, *v; 275135446Strhodes 276135446Strhodes if (isccc_alist_alistp(sexpr)) { 277135446Strhodes fprintf(stream, "{\n"); 278135446Strhodes indent += 4; 279135446Strhodes for (elt = isccc_alist_first(sexpr); 280135446Strhodes elt != NULL; 281135446Strhodes elt = CDR(elt)) { 282135446Strhodes kv = CAR(elt); 283135446Strhodes INSIST(isccc_sexpr_listp(kv)); 284135446Strhodes k = CAR(kv); 285135446Strhodes v = CDR(kv); 286135446Strhodes INSIST(isccc_sexpr_stringp(k)); 287135446Strhodes fprintf(stream, "%.*s%s => ", (int)indent, spaces, 288135446Strhodes isccc_sexpr_tostring(k)); 289135446Strhodes isccc_alist_prettyprint(v, indent, stream); 290135446Strhodes if (CDR(elt) != NULL) 291135446Strhodes fprintf(stream, ","); 292135446Strhodes fprintf(stream, "\n"); 293135446Strhodes } 294135446Strhodes indent -= 4; 295135446Strhodes fprintf(stream, "%.*s}", (int)indent, spaces); 296135446Strhodes } else if (isccc_sexpr_listp(sexpr)) { 297135446Strhodes fprintf(stream, "(\n"); 298135446Strhodes indent += 4; 299135446Strhodes for (elt = sexpr; 300135446Strhodes elt != NULL; 301135446Strhodes elt = CDR(elt)) { 302135446Strhodes fprintf(stream, "%.*s", (int)indent, spaces); 303135446Strhodes isccc_alist_prettyprint(CAR(elt), indent, stream); 304135446Strhodes if (CDR(elt) != NULL) 305135446Strhodes fprintf(stream, ","); 306135446Strhodes fprintf(stream, "\n"); 307135446Strhodes } 308135446Strhodes indent -= 4; 309135446Strhodes fprintf(stream, "%.*s)", (int)indent, spaces); 310135446Strhodes } else 311135446Strhodes isccc_sexpr_print(sexpr, stream); 312135446Strhodes} 313