1 /* $NetBSD: data.h,v 1.3 2022/04/03 01:10:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC") 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 DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 13 * ANY 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 16 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * Internet Systems Consortium, Inc. 19 * PO Box 360 20 * Newmarket, NH 03857 USA 21 * <info@isc.org> 22 * http://www.isc.org/ 23 */ 24 25 #ifndef DATA_H 26 #define DATA_H 27 28 #include <stdint.h> 29 #include <stdio.h> 30 31 /* From FreeBSD sys/queue.h */ 32 33 /* 34 * Tail queue declarations. 35 */ 36 #define TAILQ_HEAD(name, type) \ 37 struct name { \ 38 struct type *tqh_first; /* first element */ \ 39 struct type **tqh_last; /* addr of last next element */ \ 40 } 41 42 #define TAILQ_ENTRY(type) \ 43 struct { \ 44 struct type *tqe_next; /* next element */ \ 45 struct type **tqe_prev; /* address of previous next element */ \ 46 } 47 48 /* 49 * Tail queue functions. 50 */ 51 #define TAILQ_CONCAT(head1, head2) do { \ 52 if (!TAILQ_EMPTY(head2)) { \ 53 *(head1)->tqh_last = (head2)->tqh_first; \ 54 (head2)->tqh_first->next.tqe_prev = (head1)->tqh_last; \ 55 (head1)->tqh_last = (head2)->tqh_last; \ 56 TAILQ_INIT((head2)); \ 57 } \ 58 } while (0) 59 60 #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) 61 62 #define TAILQ_FIRST(head) ((head)->tqh_first) 63 64 #define TAILQ_FOREACH(var, head) \ 65 for ((var) = TAILQ_FIRST((head)); \ 66 (var); \ 67 (var) = TAILQ_NEXT((var))) 68 69 #define TAILQ_FOREACH_SAFE(var, head, tvar) \ 70 for ((var) = TAILQ_FIRST((head)); \ 71 (var) && ((tvar) = TAILQ_NEXT((var)), 1); \ 72 (var) = (tvar)) 73 74 #define TAILQ_INIT(head) do { \ 75 TAILQ_FIRST((head)) = NULL; \ 76 (head)->tqh_last = &TAILQ_FIRST((head)); \ 77 } while (0) 78 79 #define TAILQ_INSERT_AFTER(head, listelm, elm) do { \ 80 if ((TAILQ_NEXT((elm)) = TAILQ_NEXT((listelm))) != NULL) \ 81 TAILQ_NEXT((elm))->next.tqe_prev = \ 82 &TAILQ_NEXT((elm)); \ 83 else { \ 84 (head)->tqh_last = &TAILQ_NEXT((elm)); \ 85 } \ 86 TAILQ_NEXT((listelm)) = (elm); \ 87 (elm)->next.tqe_prev = &TAILQ_NEXT((listelm)); \ 88 } while (0) 89 90 #define TAILQ_INSERT_BEFORE(listelm, elm) do { \ 91 (elm)->next.tqe_prev = (listelm)->next.tqe_prev; \ 92 TAILQ_NEXT((elm)) = (listelm); \ 93 *(listelm)->next.tqe_prev = (elm); \ 94 (listelm)->next.tqe_prev = &TAILQ_NEXT((elm)); \ 95 } while (0) 96 97 #define TAILQ_INSERT_HEAD(head, elm) do { \ 98 if ((TAILQ_NEXT((elm)) = TAILQ_FIRST((head))) != NULL) \ 99 TAILQ_FIRST((head))->next.tqe_prev = \ 100 &TAILQ_NEXT((elm)); \ 101 else \ 102 (head)->tqh_last = &TAILQ_NEXT((elm)); \ 103 TAILQ_FIRST((head)) = (elm); \ 104 (elm)->next.tqe_prev = &TAILQ_FIRST((head)); \ 105 } while (0) 106 107 #define TAILQ_INSERT_TAIL(head, elm) do { \ 108 TAILQ_NEXT((elm)) = NULL; \ 109 (elm)->next.tqe_prev = (head)->tqh_last; \ 110 *(head)->tqh_last = (elm); \ 111 (head)->tqh_last = &TAILQ_NEXT((elm)); \ 112 } while (0) 113 114 #define TAILQ_LAST(head, headname) \ 115 (*(((struct headname *)((head)->tqh_last))->tqh_last)) 116 117 #define TAILQ_NEXT(elm) ((elm)->next.tqe_next) 118 119 #define TAILQ_PREV(elm, headname) \ 120 (*(((struct headname *)((elm)->next.tqe_prev))->tqh_last)) 121 122 #define TAILQ_REMOVE(head, elm) do { \ 123 if ((TAILQ_NEXT((elm))) != NULL) \ 124 TAILQ_NEXT((elm))->next.tqe_prev = \ 125 (elm)->next.tqe_prev; \ 126 else \ 127 (head)->tqh_last = (elm)->next.tqe_prev; \ 128 *(elm)->next.tqe_prev = TAILQ_NEXT((elm)); \ 129 (elm)->next.tqe_next = (void *)-1; \ 130 (elm)->next.tqe_prev = (void *)-1; \ 131 } while (0) 132 133 #define TAILQ_SWAP(head1, head2, type) do { \ 134 struct type *swap_first = (head1)->tqh_first; \ 135 struct type **swap_last = (head1)->tqh_last; \ 136 (head1)->tqh_first = (head2)->tqh_first; \ 137 (head1)->tqh_last = (head2)->tqh_last; \ 138 (head2)->tqh_first = swap_first; \ 139 (head2)->tqh_last = swap_last; \ 140 if ((swap_first = (head1)->tqh_first) != NULL) \ 141 swap_first->next.tqe_prev = &(head1)->tqh_first; \ 142 else \ 143 (head1)->tqh_last = &(head1)->tqh_first; \ 144 if ((swap_first = (head2)->tqh_first) != NULL) \ 145 swap_first->next.tqe_prev = &(head2)->tqh_first; \ 146 else \ 147 (head2)->tqh_last = &(head2)->tqh_first; \ 148 } while (0) 149 150 /* From bind9 lib/isc/include/isc/boolean.h */ 151 152 typedef enum { isc_boolean_false = 0, isc_boolean_true = 1 } isc_boolean_t; 153 154 #define ISC_FALSE isc_boolean_false 155 #define ISC_TRUE isc_boolean_true 156 #define ISC_TF(x) ((x) ? ISC_TRUE : ISC_FALSE) 157 158 /* From Kea src/lib/cc/data.h */ 159 160 struct element; 161 162 /* Element types */ 163 #define ELEMENT_NONE 0 164 #define ELEMENT_INTEGER 1 165 #define ELEMENT_REAL 2 166 #define ELEMENT_BOOLEAN 3 167 #define ELEMENT_NULL 4 168 #define ELEMENT_STRING 5 169 #define ELEMENT_LIST 6 170 #define ELEMENT_MAP 7 171 172 /* Element string */ 173 struct string { 174 size_t length; /* string length */ 175 char *content; /* string data */ 176 }; 177 178 struct string *allocString(void); 179 /* In makeString() l == -1 means use strlen(s) */ 180 struct string *makeString(int l, const char *s); 181 /* format ZlLsSbBfXI6 + h */ 182 struct string *makeStringExt(int l, const char *s, char fmt); 183 /* format 6lLIsSbBj */ 184 struct string *makeStringArray(int l, const char *s, char fmt); 185 void appendString(struct string *s, const char *a); 186 void concatString(struct string *s, const struct string *a); 187 isc_boolean_t eqString(const struct string *s, const struct string *o); 188 /* quoting */ 189 struct string *quote(struct string *); 190 191 /* Comments */ 192 struct comment { 193 char *line; /* comment line */ 194 TAILQ_ENTRY(comment) next; /* next line */ 195 }; 196 TAILQ_HEAD(comments, comment); 197 198 struct comment *createComment(const char *line); 199 200 /* Element list */ 201 TAILQ_HEAD(list, element); 202 203 /* Element map */ 204 TAILQ_HEAD(map, element); 205 206 /* Element value */ 207 union value { 208 int64_t int_value; /* integer */ 209 double double_value; /* real */ 210 isc_boolean_t bool_value; /* boolean */ 211 /**/ /* null */ 212 struct string string_value; /* string */ 213 struct list list_value; /* list */ 214 struct map map_value; /* map */ 215 }; 216 217 /* Element */ 218 struct element { 219 int type; /* element type (ELEMENT_XXX) */ 220 int kind; /* element kind (e.g. ROOT_GROUP) */ 221 isc_boolean_t skip; /* skip as not converted */ 222 char *key; /* element key (for map) */ 223 union value value; /* value */ 224 struct comments comments; /* associated comments */ 225 TAILQ_ENTRY(element) next; /* next item in list or map chain */ 226 }; 227 228 /* Value getters */ 229 int64_t intValue(const struct element *e); 230 double doubleValue(const struct element *e); 231 isc_boolean_t boolValue(const struct element *e); 232 struct string *stringValue(struct element *e); 233 struct list *listValue(struct element *e); 234 struct map *mapValue(struct element *e); 235 236 /* Creators */ 237 struct element *create(void); 238 struct element *createInt(int64_t i); 239 struct element *createDouble(double d); 240 struct element *createBool(isc_boolean_t b); 241 struct element *createNull(void); 242 struct element *createString(const struct string *s); 243 struct element *createList(void); 244 struct element *createMap(void); 245 246 /* Reset */ 247 void resetInt(struct element *e, int64_t i); 248 void resetDouble(struct element *e, double d); 249 void resetBool(struct element *e, isc_boolean_t b); 250 void resetNull(struct element *e); 251 void resetString(struct element *e, const struct string *s); 252 void resetList(struct element *e); 253 void resetMap(struct element *e); 254 void resetBy(struct element *e, struct element *o); 255 256 /* List functions */ 257 struct element *listGet(struct element *l, int i); 258 void listSet(struct element *l, struct element *e, int i); 259 void listPush(struct element *l, struct element *e); 260 void listRemove(struct element *l, int i); 261 size_t listSize(const struct element *l); 262 void concat(struct element *l, struct element *o); 263 264 /* Map functions */ 265 struct element *mapGet(struct element *m, const char *k); 266 void mapSet(struct element *m, struct element *e, const char *k); 267 void mapRemove(struct element *m, const char *k); 268 isc_boolean_t mapContains(const struct element *m, const char *k); 269 size_t mapSize(const struct element *m); 270 void merge(struct element *m, struct element *o); 271 272 /* Tools */ 273 const char *type2name(int t); 274 int name2type(const char *n); 275 void print(FILE *fp, const struct element *e, 276 isc_boolean_t skip, unsigned indent); 277 void printList(FILE *fp, const struct list *l, 278 isc_boolean_t skip, unsigned indent); 279 void printMap(FILE *fp, const struct map *m, 280 isc_boolean_t skip, unsigned indent); 281 void printString(FILE *fp, const struct string *s); 282 isc_boolean_t skip_to_end(const struct element *e); 283 284 struct element *copy(struct element *e); 285 struct element *copyList(struct element *l); 286 struct element *copyMap(struct element *m); 287 288 /* Handles */ 289 TAILQ_HEAD(handles, handle); 290 291 struct handle { 292 unsigned order; /* order */ 293 char *key; /* key */ 294 struct element *value; /* value */ 295 struct handles values; /* children */ 296 TAILQ_ENTRY(handle) next; /* siblings */ 297 }; 298 299 struct handle* mapPop(struct element *); 300 void derive(struct handle *, struct handle *); 301 302 /* Hexadecimal literals */ 303 struct string *hexaValue(struct element *); 304 struct element *createHexa(struct string *); 305 306 #endif /* DATA_H */ 307