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