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) \ 37struct 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) \ 43struct { \ 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 152typedef 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 160struct 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 */ 173struct string { 174 size_t length; /* string length */ 175 char *content; /* string data */ 176}; 177 178struct string *allocString(void); 179/* In makeString() l == -1 means use strlen(s) */ 180struct string *makeString(int l, const char *s); 181/* format ZlLsSbBfXI6 + h */ 182struct string *makeStringExt(int l, const char *s, char fmt); 183/* format 6lLIsSbBj */ 184struct string *makeStringArray(int l, const char *s, char fmt); 185void appendString(struct string *s, const char *a); 186void concatString(struct string *s, const struct string *a); 187isc_boolean_t eqString(const struct string *s, const struct string *o); 188/* quoting */ 189struct string *quote(struct string *); 190 191/* Comments */ 192struct comment { 193 char *line; /* comment line */ 194 TAILQ_ENTRY(comment) next; /* next line */ 195}; 196TAILQ_HEAD(comments, comment); 197 198struct comment *createComment(const char *line); 199 200/* Element list */ 201TAILQ_HEAD(list, element); 202 203/* Element map */ 204TAILQ_HEAD(map, element); 205 206/* Element value */ 207union 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 */ 218struct 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 */ 229int64_t intValue(const struct element *e); 230double doubleValue(const struct element *e); 231isc_boolean_t boolValue(const struct element *e); 232struct string *stringValue(struct element *e); 233struct list *listValue(struct element *e); 234struct map *mapValue(struct element *e); 235 236/* Creators */ 237struct element *create(void); 238struct element *createInt(int64_t i); 239struct element *createDouble(double d); 240struct element *createBool(isc_boolean_t b); 241struct element *createNull(void); 242struct element *createString(const struct string *s); 243struct element *createList(void); 244struct element *createMap(void); 245 246/* Reset */ 247void resetInt(struct element *e, int64_t i); 248void resetDouble(struct element *e, double d); 249void resetBool(struct element *e, isc_boolean_t b); 250void resetNull(struct element *e); 251void resetString(struct element *e, const struct string *s); 252void resetList(struct element *e); 253void resetMap(struct element *e); 254void resetBy(struct element *e, struct element *o); 255 256/* List functions */ 257struct element *listGet(struct element *l, int i); 258void listSet(struct element *l, struct element *e, int i); 259void listPush(struct element *l, struct element *e); 260void listRemove(struct element *l, int i); 261size_t listSize(const struct element *l); 262void concat(struct element *l, struct element *o); 263 264/* Map functions */ 265struct element *mapGet(struct element *m, const char *k); 266void mapSet(struct element *m, struct element *e, const char *k); 267void mapRemove(struct element *m, const char *k); 268isc_boolean_t mapContains(const struct element *m, const char *k); 269size_t mapSize(const struct element *m); 270void merge(struct element *m, struct element *o); 271 272/* Tools */ 273const char *type2name(int t); 274int name2type(const char *n); 275void print(FILE *fp, const struct element *e, 276 isc_boolean_t skip, unsigned indent); 277void printList(FILE *fp, const struct list *l, 278 isc_boolean_t skip, unsigned indent); 279void printMap(FILE *fp, const struct map *m, 280 isc_boolean_t skip, unsigned indent); 281void printString(FILE *fp, const struct string *s); 282isc_boolean_t skip_to_end(const struct element *e); 283 284struct element *copy(struct element *e); 285struct element *copyList(struct element *l); 286struct element *copyMap(struct element *m); 287 288/* Handles */ 289TAILQ_HEAD(handles, handle); 290 291struct 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 299struct handle* mapPop(struct element *); 300void derive(struct handle *, struct handle *); 301 302/* Hexadecimal literals */ 303struct string *hexaValue(struct element *); 304struct element *createHexa(struct string *); 305 306#endif /* DATA_H */ 307