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