/contrib/bind9/lib/isccc/alist.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 312 lines · 227 code · 44 blank · 41 comment · 72 complexity · a79b393dc00e62d4f8c9444995446629 MD5 · raw file

  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. /* $Id: alist.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */
  32. /*! \file */
  33. #include <config.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <isccc/alist.h>
  37. #include <isc/assertions.h>
  38. #include <isccc/result.h>
  39. #include <isccc/sexpr.h>
  40. #include <isccc/util.h>
  41. #define CAR(s) (s)->value.as_dottedpair.car
  42. #define CDR(s) (s)->value.as_dottedpair.cdr
  43. #define ALIST_TAG "*alist*"
  44. #define MAX_INDENT 64
  45. static char spaces[MAX_INDENT + 1] =
  46. " ";
  47. isccc_sexpr_t *
  48. isccc_alist_create(void)
  49. {
  50. isccc_sexpr_t *alist, *tag;
  51. tag = isccc_sexpr_fromstring(ALIST_TAG);
  52. if (tag == NULL)
  53. return (NULL);
  54. alist = isccc_sexpr_cons(tag, NULL);
  55. if (alist == NULL) {
  56. isccc_sexpr_free(&tag);
  57. return (NULL);
  58. }
  59. return (alist);
  60. }
  61. isc_boolean_t
  62. isccc_alist_alistp(isccc_sexpr_t *alist)
  63. {
  64. isccc_sexpr_t *car;
  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. isc_boolean_t
  75. isccc_alist_emptyp(isccc_sexpr_t *alist)
  76. {
  77. REQUIRE(isccc_alist_alistp(alist));
  78. if (CDR(alist) == NULL)
  79. return (ISC_TRUE);
  80. return (ISC_FALSE);
  81. }
  82. isccc_sexpr_t *
  83. isccc_alist_first(isccc_sexpr_t *alist)
  84. {
  85. REQUIRE(isccc_alist_alistp(alist));
  86. return (CDR(alist));
  87. }
  88. isccc_sexpr_t *
  89. isccc_alist_assq(isccc_sexpr_t *alist, const char *key)
  90. {
  91. isccc_sexpr_t *car, *caar;
  92. REQUIRE(isccc_alist_alistp(alist));
  93. /*
  94. * Skip alist type tag.
  95. */
  96. alist = CDR(alist);
  97. while (alist != NULL) {
  98. INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
  99. car = CAR(alist);
  100. INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
  101. caar = CAR(car);
  102. if (caar->type == ISCCC_SEXPRTYPE_STRING &&
  103. strcmp(caar->value.as_string, key) == 0)
  104. return (car);
  105. alist = CDR(alist);
  106. }
  107. return (NULL);
  108. }
  109. void
  110. isccc_alist_delete(isccc_sexpr_t *alist, const char *key)
  111. {
  112. isccc_sexpr_t *car, *caar, *rest, *prev;
  113. REQUIRE(isccc_alist_alistp(alist));
  114. prev = alist;
  115. rest = CDR(alist);
  116. while (rest != NULL) {
  117. INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
  118. car = CAR(rest);
  119. INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
  120. caar = CAR(car);
  121. if (caar->type == ISCCC_SEXPRTYPE_STRING &&
  122. strcmp(caar->value.as_string, key) == 0) {
  123. CDR(prev) = CDR(rest);
  124. CDR(rest) = NULL;
  125. isccc_sexpr_free(&rest);
  126. break;
  127. }
  128. prev = rest;
  129. rest = CDR(rest);
  130. }
  131. }
  132. isccc_sexpr_t *
  133. isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value)
  134. {
  135. isccc_sexpr_t *kv, *k, *elt;
  136. kv = isccc_alist_assq(alist, key);
  137. if (kv == NULL) {
  138. /*
  139. * New association.
  140. */
  141. k = isccc_sexpr_fromstring(key);
  142. if (k == NULL)
  143. return (NULL);
  144. kv = isccc_sexpr_cons(k, value);
  145. if (kv == NULL) {
  146. isccc_sexpr_free(&kv);
  147. return (NULL);
  148. }
  149. elt = isccc_sexpr_addtolist(&alist, kv);
  150. if (elt == NULL) {
  151. isccc_sexpr_free(&kv);
  152. return (NULL);
  153. }
  154. } else {
  155. /*
  156. * We've already got an entry for this key. Replace it.
  157. */
  158. isccc_sexpr_free(&CDR(kv));
  159. CDR(kv) = value;
  160. }
  161. return (kv);
  162. }
  163. isccc_sexpr_t *
  164. isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
  165. {
  166. isccc_sexpr_t *v, *kv;
  167. v = isccc_sexpr_fromstring(str);
  168. if (v == NULL)
  169. return (NULL);
  170. kv = isccc_alist_define(alist, key, v);
  171. if (kv == NULL)
  172. isccc_sexpr_free(&v);
  173. return (kv);
  174. }
  175. isccc_sexpr_t *
  176. isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r)
  177. {
  178. isccc_sexpr_t *v, *kv;
  179. v = isccc_sexpr_frombinary(r);
  180. if (v == NULL)
  181. return (NULL);
  182. kv = isccc_alist_define(alist, key, v);
  183. if (kv == NULL)
  184. isccc_sexpr_free(&v);
  185. return (kv);
  186. }
  187. isccc_sexpr_t *
  188. isccc_alist_lookup(isccc_sexpr_t *alist, const char *key)
  189. {
  190. isccc_sexpr_t *kv;
  191. kv = isccc_alist_assq(alist, key);
  192. if (kv != NULL)
  193. return (CDR(kv));
  194. return (NULL);
  195. }
  196. isc_result_t
  197. isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
  198. {
  199. isccc_sexpr_t *kv, *v;
  200. kv = isccc_alist_assq(alist, key);
  201. if (kv != NULL) {
  202. v = CDR(kv);
  203. if (isccc_sexpr_stringp(v)) {
  204. if (strp != NULL)
  205. *strp = isccc_sexpr_tostring(v);
  206. return (ISC_R_SUCCESS);
  207. } else
  208. return (ISC_R_EXISTS);
  209. }
  210. return (ISC_R_NOTFOUND);
  211. }
  212. isc_result_t
  213. isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r)
  214. {
  215. isccc_sexpr_t *kv, *v;
  216. kv = isccc_alist_assq(alist, key);
  217. if (kv != NULL) {
  218. v = CDR(kv);
  219. if (isccc_sexpr_binaryp(v)) {
  220. if (r != NULL)
  221. *r = isccc_sexpr_tobinary(v);
  222. return (ISC_R_SUCCESS);
  223. } else
  224. return (ISC_R_EXISTS);
  225. }
  226. return (ISC_R_NOTFOUND);
  227. }
  228. void
  229. isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream)
  230. {
  231. isccc_sexpr_t *elt, *kv, *k, *v;
  232. if (isccc_alist_alistp(sexpr)) {
  233. fprintf(stream, "{\n");
  234. indent += 4;
  235. for (elt = isccc_alist_first(sexpr);
  236. elt != NULL;
  237. elt = CDR(elt)) {
  238. kv = CAR(elt);
  239. INSIST(isccc_sexpr_listp(kv));
  240. k = CAR(kv);
  241. v = CDR(kv);
  242. INSIST(isccc_sexpr_stringp(k));
  243. fprintf(stream, "%.*s%s => ", (int)indent, spaces,
  244. isccc_sexpr_tostring(k));
  245. isccc_alist_prettyprint(v, indent, stream);
  246. if (CDR(elt) != NULL)
  247. fprintf(stream, ",");
  248. fprintf(stream, "\n");
  249. }
  250. indent -= 4;
  251. fprintf(stream, "%.*s}", (int)indent, spaces);
  252. } else if (isccc_sexpr_listp(sexpr)) {
  253. fprintf(stream, "(\n");
  254. indent += 4;
  255. for (elt = sexpr;
  256. elt != NULL;
  257. elt = CDR(elt)) {
  258. fprintf(stream, "%.*s", (int)indent, spaces);
  259. isccc_alist_prettyprint(CAR(elt), indent, stream);
  260. if (CDR(elt) != NULL)
  261. fprintf(stream, ",");
  262. fprintf(stream, "\n");
  263. }
  264. indent -= 4;
  265. fprintf(stream, "%.*s)", (int)indent, spaces);
  266. } else
  267. isccc_sexpr_print(sexpr, stream);
  268. }