1 /* $NetBSD: data.c,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 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: data.c,v 1.3 2022/04/03 01:10:59 christos Exp $");
27
28 #include "data.h"
29
30 #include <sys/types.h>
31 #include <arpa/inet.h>
32 #include <assert.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 struct string *
allocString(void)37 allocString(void)
38 {
39 struct string *result;
40
41 result = (struct string *)malloc(sizeof(struct string));
42 assert(result != NULL);
43 memset(result, 0, sizeof(struct string));
44
45 return result;
46 }
47
48 struct string *
makeString(int l,const char * s)49 makeString(int l, const char *s)
50 {
51 struct string *result;
52
53 result = allocString();
54 if (l < 0)
55 result->length = strlen(s);
56 else
57 result->length = (size_t)l;
58 if (result->length > 0) {
59 result->content = (char *)malloc(result->length + 1);
60 assert(result->content != NULL);
61 memcpy(result->content, s, result->length);
62 result->content[result->length] = 0;
63 }
64
65 return result;
66 }
67
68 struct string *
makeStringExt(int l,const char * s,char fmt)69 makeStringExt(int l, const char *s, char fmt)
70 {
71 switch (fmt) {
72 case 'Z':
73 /* zero-length */
74 return allocString();
75
76 case 'l': {
77 /* 32-bit signed integer */
78 int32_t x;
79 char buf[40];
80
81 assert(s != NULL);
82 assert(l > 3);
83
84 memcpy(&x, s, 4);
85 x = (int32_t)ntohl((uint32_t)x);
86 snprintf(buf, sizeof(buf), "%lld", (long long)x);
87 return makeString(-1, buf);
88 }
89
90 case 'L': {
91 /* 32-bit unsigned integer */
92 uint32_t x;
93 char buf[40];
94
95 assert(s != NULL);
96 assert(l > 3);
97
98 memcpy(&x, s, 4);
99 x = ntohl(x);
100 snprintf(buf, sizeof(buf), "%llu", (unsigned long long)x);
101 return makeString(-1, buf);
102 }
103
104 case 's': {
105 /* 16-bit signed integer */
106 int16_t x;
107 char buf[20];
108
109 assert(s != NULL);
110 assert(l > 1);
111
112 memcpy(&x, s, 2);
113 x = (int16_t)ntohs((uint16_t)x);
114 snprintf(buf, sizeof(buf), "%hd", x);
115 return makeString(-1, buf);
116 }
117
118 case 'S': {
119 /* 16-bit unsigned integer */
120 uint16_t x;
121 char buf[20];
122
123 assert(s != NULL);
124 assert(l > 1);
125
126 memcpy(&x, s, 2);
127 x = ntohs(x);
128 snprintf(buf, sizeof(buf), "%hu", x);
129 return makeString(-1, buf);
130 }
131
132 case 'b': {
133 /* 8-bit signed integer */
134 int8_t x;
135 char buf[10];
136
137 assert(s != NULL);
138 assert(l > 0);
139
140 memcpy(&x, s, 1);
141 snprintf(buf, sizeof(buf), "%hhd", x);
142 return makeString(-1, buf);
143 }
144
145 case 'B': {
146 /* 8-bit unsigned integer */
147 uint8_t x;
148 char buf[10];
149
150 assert(s != NULL);
151 assert(l > 0);
152
153 memcpy(&x, s, 1);
154 snprintf(buf, sizeof(buf), "%hhu", x);
155 return makeString(-1, buf);
156 }
157
158 case 'f': {
159 /* flag (true or false) */
160 uint8_t f;
161
162 assert(s != NULL);
163 assert(l > 0);
164
165 f = *s;
166 return makeString(-1, f ? "true" : "false");
167 }
168
169 case 'X': {
170 /* binary data */
171 struct string *result;
172 size_t i;
173 char buf[4];
174
175 assert((l == 0) || (s != NULL));
176
177 result = allocString();
178 for (i = 0; i < l; i++) {
179 snprintf(buf, sizeof(buf), "%02hhx", (uint8_t)s[i]);
180 appendString(result, buf);
181 }
182 return result;
183 }
184
185 case 'H': {
186 /* binary data with colons */
187 struct string *result;
188 size_t i;
189 isc_boolean_t first = ISC_TRUE;
190 char buf[4];
191
192 assert((l == 0) || (s != NULL));
193
194 result = allocString();
195 for (i = 0; i < l; i++) {
196 if (!first)
197 appendString(result, ":");
198 first = ISC_FALSE;
199 snprintf(buf, sizeof(buf), "%02hhx", (uint8_t)s[i]);
200 appendString(result, buf);
201 }
202 return result;
203 }
204
205 case 'I': {
206 /* IPv4 address to text */
207 char buf[40 /* INET_ADDRSTRLEN == 26 */];
208
209 assert(l > 3);
210 assert(inet_ntop(AF_INET, s, buf, sizeof(buf)) != NULL);
211 return makeString(-1, buf);
212 }
213
214 case 'i': {
215 /* IPv4 address to hexa */
216 uint8_t a[4];
217 char buf[10];
218
219 assert(inet_pton(AF_INET, s, a) == 1);
220 snprintf(buf, sizeof(buf), "%02hhx%02hhx%02hhx%02hhx",
221 a[0], a[1], a[2], a[3]);
222 return makeString(-1, buf);
223 }
224
225 case '6': {
226 /* IPv6 address */
227 char buf[80 /* INET6_ADDRSTRLEN == 46 */];
228
229 assert(l > 15);
230 assert(inet_ntop(AF_INET6, s, buf, sizeof(buf)) != NULL);
231 return makeString(-1, buf);
232 }
233
234 case 'd': {
235 /* FQDN to DNS wire format */
236 struct string *result;
237 const char *p;
238 const char *dot;
239 char ll;
240
241 assert(s[l] == '0');
242
243 result = allocString();
244 p = s;
245 while ((dot = strchr(p, '.')) != NULL) {
246 int len;
247
248 len = dot - p - 1;
249 if ((len & 0xc0) != 0)
250 return NULL;
251 if (dot - s >= l)
252 return NULL;
253 ll = len & 0x3f;
254 concatString(result, makeString(1, &ll));
255 concatString(result, makeString(len, p));
256 p = dot + 1;
257 if (p - s == l)
258 break;
259 }
260 if (dot == NULL) {
261 ll = 0;
262 concatString(result, makeString(1, &ll));
263 }
264 return result;
265 }
266
267 default:
268 assert(0);
269 }
270 }
271
272 struct string *
makeStringArray(int l,const char * s,char fmt)273 makeStringArray(int l, const char *s, char fmt)
274 {
275 struct string *result;
276 size_t step;
277 isc_boolean_t first = ISC_TRUE;
278
279 switch (fmt) {
280 case '6':
281 step = 16;
282 break;
283 case 'l':
284 case 'L':
285 case 'I':
286 step = 4;
287 break;
288 case 's':
289 case 'S':
290 step = 2;
291 break;
292 case 'b':
293 case 'B':
294 case 'f':
295 step = 1;
296 break;
297 default:
298 assert(0);
299 }
300
301 assert((l % step) == 0);
302
303 result = allocString();
304 while (l > 0) {
305 if (!first)
306 appendString(result, ",");
307 first = ISC_FALSE;
308 concatString(result, makeStringExt(l, s, fmt));
309 s += step;
310 l -= step;
311 }
312 return result;
313 }
314
315 void
appendString(struct string * s,const char * a)316 appendString(struct string *s, const char *a)
317 {
318 size_t n;
319
320 assert(s != NULL);
321
322 if (a == NULL)
323 return;
324 n = strlen(a);
325 if (n == 0)
326 return;
327 s->content = (char *)realloc(s->content, s->length + n + 1);
328 assert(s->content != NULL);
329 memcpy(s->content + s->length, a, n);
330 s->length += n;
331 s->content[s->length] = 0;
332 }
333
334 void
concatString(struct string * s,const struct string * a)335 concatString(struct string *s, const struct string *a)
336 {
337 assert(s != NULL);
338 assert(a != NULL);
339
340 s->content = (char *)realloc(s->content, s->length + a->length + 1);
341 assert(s->content != NULL);
342 memcpy(s->content + s->length, a->content, a->length);
343 s->length += a->length;
344 s->content[s->length] = 0;
345 }
346
347 isc_boolean_t
eqString(const struct string * s,const struct string * o)348 eqString(const struct string *s, const struct string *o)
349 {
350 assert(s != NULL);
351 assert(o != NULL);
352
353 if (s->length != o->length)
354 return ISC_FALSE;
355 if (s->length == 0)
356 return ISC_TRUE;
357 return ISC_TF(memcmp(s->content, o->content, s->length) == 0);
358 }
359
360 struct string *
quote(struct string * s)361 quote(struct string *s)
362 {
363 struct string *result;
364
365 result = makeString(-1, "'");
366 concatString(result, s);
367 appendString(result, "'");
368 return result;
369 }
370
371 struct comment *
createComment(const char * line)372 createComment(const char *line)
373 {
374 struct comment *comment;
375
376 assert(line != NULL);
377
378 comment = (struct comment *)malloc(sizeof(struct comment));
379 assert(comment != NULL);
380 memset(comment, 0, sizeof(struct comment));
381
382 comment->line = strdup(line);
383
384 return comment;
385 }
386
387 int64_t
intValue(const struct element * e)388 intValue(const struct element *e)
389 {
390 assert(e != NULL);
391 assert(e->type == ELEMENT_INTEGER);
392 return e->value.int_value;
393 }
394
395 double
doubleValue(const struct element * e)396 doubleValue(const struct element *e)
397 {
398 assert(e != NULL);
399 assert(e->type == ELEMENT_REAL);
400 return e->value.double_value;
401 }
402
403 isc_boolean_t
boolValue(const struct element * e)404 boolValue(const struct element *e)
405 {
406 assert(e != NULL);
407 assert(e->type == ELEMENT_BOOLEAN);
408 /* could check if 0 or 1 */
409 return e->value.bool_value;
410 }
411
412 struct string *
stringValue(struct element * e)413 stringValue(struct element *e)
414 {
415 assert(e != NULL);
416 assert(e->type == ELEMENT_STRING);
417 return &e->value.string_value;
418 }
419
420 struct list *
listValue(struct element * e)421 listValue(struct element *e)
422 {
423 assert(e != NULL);
424 assert(e->type == ELEMENT_LIST);
425 return &e->value.list_value;
426 }
427
428 struct map *
mapValue(struct element * e)429 mapValue(struct element *e)
430 {
431 assert(e != NULL);
432 assert(e->type == ELEMENT_MAP);
433 return &e->value.map_value;
434 }
435
436 struct element *
create(void)437 create(void)
438 {
439 struct element *elem;
440
441 elem = (struct element *)malloc(sizeof(struct element));
442 assert(elem != NULL);
443 memset(elem, 0, sizeof(struct element));
444 TAILQ_INIT(&elem->comments);
445
446 return elem;
447 }
448
449 struct element *
createInt(int64_t i)450 createInt(int64_t i)
451 {
452 struct element *elem;
453
454 elem = create();
455 elem->type = ELEMENT_INTEGER;
456 elem->value.int_value = i;
457
458 return elem;
459 }
460
461 struct element *
createDouble(double d)462 createDouble(double d)
463 {
464 struct element *elem;
465
466 elem = create();
467 elem->type = ELEMENT_REAL;
468 elem->value.double_value = d;
469
470 return elem;
471 }
472
473 struct element *
createBool(isc_boolean_t b)474 createBool(isc_boolean_t b)
475 {
476 struct element *elem;
477
478 elem = create();
479 elem->type = ELEMENT_BOOLEAN;
480 elem->value.bool_value = b;
481
482 return elem;
483 }
484
485 struct element *
createNull(void)486 createNull(void)
487 {
488 struct element *elem;
489
490 elem = create();
491 elem->type = ELEMENT_NULL;
492
493 return elem;
494 }
495
496 struct element *
createString(const struct string * s)497 createString(const struct string *s)
498 {
499 struct element *elem;
500
501 elem = create();
502 elem->type = ELEMENT_STRING;
503 elem->value.string_value = *s;
504
505 return elem;
506 }
507
508 struct element *
createList(void)509 createList(void)
510 {
511 struct element *elem;
512
513 elem = create();
514 elem->type = ELEMENT_LIST;
515 TAILQ_INIT(&elem->value.list_value);
516
517 return elem;
518 }
519
520 struct element *
createMap(void)521 createMap(void)
522 {
523 struct element *elem;
524
525 elem = create();
526 elem->type = ELEMENT_MAP;
527 TAILQ_INIT(&elem->value.map_value);
528
529 return elem;
530 }
531
532 static void
reset(struct element * e)533 reset(struct element *e)
534 {
535 e->type = 0;
536 e->kind = 0;
537 assert(e->key == NULL);
538 memset(&e->value, 0, sizeof(e->value));
539 }
540
541 void
resetInt(struct element * e,int64_t i)542 resetInt(struct element *e, int64_t i)
543 {
544 assert(e != NULL);
545
546 reset(e);
547 e->type = ELEMENT_INTEGER;
548 e->value.int_value = i;
549 }
550
551 void
resetDouble(struct element * e,double d)552 resetDouble(struct element *e, double d)
553 {
554 assert(e != NULL);
555
556 reset(e);
557 e->type = ELEMENT_REAL;
558 e->value.double_value = d;
559 }
560
561 void
resetBool(struct element * e,isc_boolean_t b)562 resetBool(struct element *e, isc_boolean_t b)
563 {
564 assert(e != NULL);
565
566 reset(e);
567 e->type = ELEMENT_BOOLEAN;
568 e->value.bool_value = b;
569 }
570
resetNull(struct element * e)571 void resetNull(struct element *e)
572 {
573 assert(e != NULL);
574
575 reset(e);
576 e->type = ELEMENT_NULL;
577 }
578
579 void
resetString(struct element * e,const struct string * s)580 resetString(struct element *e, const struct string *s)
581 {
582 assert(e != NULL);
583
584 reset(e);
585 e->type = ELEMENT_STRING;
586 e->value.string_value = *s;
587 }
588
589 void
resetList(struct element * e)590 resetList(struct element *e)
591 {
592 assert(e != NULL);
593
594 reset(e);
595 e->type = ELEMENT_LIST;
596 TAILQ_INIT(&e->value.list_value);
597 }
598
599 void
resetMap(struct element * e)600 resetMap(struct element *e)
601 {
602 assert(e != NULL);
603
604 reset(e);
605 e->type = ELEMENT_MAP;
606 TAILQ_INIT(&e->value.map_value);
607 }
608
609 void
resetBy(struct element * e,struct element * o)610 resetBy(struct element *e, struct element *o)
611 {
612 assert(e != NULL);
613 assert(o != NULL);
614
615 reset(e);
616 e->type = o->type;
617 e->kind = o->kind;
618 e->skip = o->skip;
619 e->key = o->key;
620 o->key = NULL;
621 TAILQ_CONCAT(&e->comments, &o->comments);
622
623 switch (e->type) {
624 case ELEMENT_INTEGER:
625 e->value.int_value = o->value.int_value;
626 break;
627 case ELEMENT_REAL:
628 e->value.double_value = o->value.double_value;
629 break;
630 case ELEMENT_BOOLEAN:
631 e->value.bool_value = o->value.bool_value;
632 break;
633 case ELEMENT_STRING:
634 e->value.string_value = o->value.string_value;
635 break;
636 case ELEMENT_LIST:
637 TAILQ_INIT(&e->value.list_value);
638 TAILQ_CONCAT(&e->value.list_value, &o->value.list_value);
639 break;
640 case ELEMENT_MAP:
641 TAILQ_INIT(&e->value.map_value);
642 TAILQ_CONCAT(&e->value.map_value, &o->value.map_value);
643 break;
644 default:
645 assert(0);
646 }
647 reset(o);
648 }
649
650 struct element *
listGet(struct element * l,int i)651 listGet(struct element *l, int i)
652 {
653 struct element *elem;
654
655 assert(l != NULL);
656 assert(l->type == ELEMENT_LIST);
657 assert(i >= 0);
658
659 elem = TAILQ_FIRST(&l->value.list_value);
660 assert(elem != NULL);
661 assert(elem->key == NULL);
662
663 unsigned j;
664 for (j = i; j > 0; --j) {
665 elem = TAILQ_NEXT(elem);
666 assert(elem != NULL);
667 assert(elem->key == NULL);
668 }
669
670 return elem;
671 }
672
673 void
listSet(struct element * l,struct element * e,int i)674 listSet(struct element *l, struct element *e, int i)
675 {
676 assert(l != NULL);
677 assert(l->type == ELEMENT_LIST);
678 assert(e != NULL);
679 assert(i >= 0);
680
681 if (i == 0) {
682 TAILQ_INSERT_HEAD(&l->value.list_value, e);
683 } else {
684 struct element *prev;
685
686 prev = TAILQ_FIRST(&l->value.list_value);
687 assert(prev != NULL);
688 assert(prev->key == NULL);
689
690 unsigned j;
691 for (j = i; j > 1; --j) {
692 prev = TAILQ_NEXT(prev);
693 assert(prev != NULL);
694 assert(prev->key == NULL);
695 }
696
697 TAILQ_INSERT_AFTER(&l->value.list_value, prev, e);
698 }
699 }
700
701 void
listPush(struct element * l,struct element * e)702 listPush(struct element *l, struct element *e)
703 {
704 assert(l != NULL);
705 assert(l->type == ELEMENT_LIST);
706 assert(e != NULL);
707
708 TAILQ_INSERT_TAIL(&l->value.list_value, e);
709 }
710
711 void
listRemove(struct element * l,int i)712 listRemove(struct element *l, int i)
713 {
714 struct element *elem;
715
716 assert(l != NULL);
717 assert(l->type == ELEMENT_LIST);
718 assert(i >= 0);
719
720 elem = TAILQ_FIRST(&l->value.list_value);
721 assert(elem != NULL);
722 assert(elem->key == NULL);
723
724 unsigned j;
725 for (j = i; j > 0; --j) {
726 elem = TAILQ_NEXT(elem);
727 assert(elem != NULL);
728 assert(elem->key == NULL);
729 }
730
731 TAILQ_REMOVE(&l->value.list_value, elem);
732 }
733
734 size_t
listSize(const struct element * l)735 listSize(const struct element *l)
736 {
737 struct element *elem;
738 size_t cnt;
739
740 assert(l != NULL);
741 assert(l->type == ELEMENT_LIST);
742
743 cnt = 0;
744 TAILQ_FOREACH(elem, &l->value.list_value) {
745 assert(elem->key == NULL);
746 cnt++;
747 }
748
749 return cnt;
750 }
751
752 void
concat(struct element * l,struct element * o)753 concat(struct element *l, struct element *o)
754 {
755 assert(l != NULL);
756 assert(l->type == ELEMENT_LIST);
757 assert(o != NULL);
758 assert(o->type == ELEMENT_LIST);
759
760 TAILQ_CONCAT(&l->value.list_value, &o->value.list_value);
761 }
762
763 struct element *
mapGet(struct element * m,const char * k)764 mapGet(struct element *m, const char *k)
765 {
766 struct element *elem;
767
768 assert(m != NULL);
769 assert(m->type == ELEMENT_MAP);
770 assert(k != NULL);
771
772 TAILQ_FOREACH(elem, &m->value.map_value) {
773 assert(elem->key != NULL);
774 if (strcmp(elem->key, k) == 0)
775 break;
776 }
777
778 return elem;
779 }
780
781 void
mapSet(struct element * m,struct element * e,const char * k)782 mapSet(struct element *m, struct element *e, const char *k)
783 {
784 assert(m != NULL);
785 assert(m->type == ELEMENT_MAP);
786 assert(e != NULL);
787 assert(k != NULL);
788 #if 0
789 assert(mapGet(m, k) == NULL);
790 #endif
791 e->key = strdup(k);
792 assert(e->key != NULL);
793 TAILQ_INSERT_TAIL(&m->value.map_value, e);
794 }
795
796 void
mapRemove(struct element * m,const char * k)797 mapRemove(struct element *m, const char *k)
798 {
799 struct element *elem;
800
801 assert(m != NULL);
802 assert(m->type == ELEMENT_MAP);
803 assert(k != NULL);
804
805 TAILQ_FOREACH(elem, &m->value.map_value) {
806 assert(elem->key != NULL);
807 if (strcmp(elem->key, k) == 0)
808 break;
809 }
810
811 assert(elem != NULL);
812 TAILQ_REMOVE(&m->value.map_value, elem);
813 }
814
815 isc_boolean_t
mapContains(const struct element * m,const char * k)816 mapContains(const struct element *m, const char *k)
817 {
818 struct element *elem;
819
820 assert(m != NULL);
821 assert(m->type == ELEMENT_MAP);
822 assert(k != NULL);
823
824 TAILQ_FOREACH(elem, &m->value.map_value) {
825 assert(elem->key != NULL);
826 if (strcmp(elem->key, k) == 0)
827 break;
828 }
829
830 return ISC_TF(elem != NULL);
831 }
832
833 size_t
mapSize(const struct element * m)834 mapSize(const struct element *m)
835 {
836 struct element *elem;
837 size_t cnt;
838
839 assert(m != NULL);
840 assert(m->type == ELEMENT_MAP);
841
842 cnt = 0;
843 TAILQ_FOREACH(elem, &m->value.map_value) {
844 assert(elem->key != NULL);
845 cnt++;
846 }
847
848 return cnt;
849 }
850
851 void
merge(struct element * m,struct element * o)852 merge(struct element *m, struct element *o)
853 {
854 struct element *elem;
855 struct element *ne;
856
857 assert(m != NULL);
858 assert(m->type == ELEMENT_MAP);
859 assert(o != NULL);
860 assert(o->type == ELEMENT_MAP);
861
862 TAILQ_FOREACH_SAFE(elem, &o->value.map_value, ne) {
863 assert(elem->key != NULL);
864 TAILQ_REMOVE(&o->value.map_value, elem);
865 if (!mapContains(m, elem->key)) {
866 TAILQ_INSERT_TAIL(&m->value.map_value, elem);
867 }
868 }
869 }
870
871 const char *
type2name(int t)872 type2name(int t)
873 {
874 switch (t) {
875 case ELEMENT_NONE:
876 return "not initialized?";
877 case ELEMENT_INTEGER:
878 return "integer";
879 case ELEMENT_REAL:
880 return "real";
881 case ELEMENT_BOOLEAN:
882 return "boolean";
883 case ELEMENT_NULL:
884 return "(unused) null";
885 case ELEMENT_STRING:
886 return "string";
887 case ELEMENT_LIST:
888 return "list";
889 case ELEMENT_MAP:
890 return "map";
891 default:
892 #if 0
893 assert(0);
894 #endif
895 return "unknown?";
896 }
897 }
898
899 int
name2type(const char * n)900 name2type(const char *n)
901 {
902 assert(n != NULL);
903 if (strcmp(n, "integer") == 0)
904 return ELEMENT_INTEGER;
905 if (strcmp(n, "real") == 0)
906 return ELEMENT_REAL;
907 if (strcmp(n, "boolean") == 0)
908 return ELEMENT_BOOLEAN;
909 if (strcmp(n, "null") == 0)
910 return ELEMENT_NULL;
911 if (strcmp(n, "string") == 0)
912 return ELEMENT_STRING;
913 if (strcmp(n, "list") == 0)
914 return ELEMENT_LIST;
915 if (strcmp(n, "map") == 0)
916 return ELEMENT_MAP;
917 #if 0
918 assert(0);
919 #endif
920 return ELEMENT_NONE;
921 }
922
923 void
print(FILE * fp,const struct element * e,isc_boolean_t skip,unsigned indent)924 print(FILE *fp, const struct element *e, isc_boolean_t skip, unsigned indent)
925 {
926 assert(fp != NULL);
927 assert(e != NULL);
928
929 switch (e->type) {
930 case ELEMENT_LIST:
931 printList(fp, &e->value.list_value, skip, indent);
932 return;
933 case ELEMENT_MAP:
934 printMap(fp, &e->value.map_value, skip, indent);
935 return;
936 case ELEMENT_STRING:
937 printString(fp, &e->value.string_value);
938 return;
939 case ELEMENT_INTEGER:
940 fprintf(fp, "%lld", (long long)e->value.int_value);
941 return;
942 case ELEMENT_REAL:
943 fprintf(fp, "%f", e->value.double_value);
944 return;
945 case ELEMENT_BOOLEAN:
946 if (e->value.bool_value)
947 fprintf(fp, "true");
948 else
949 fprintf(fp, "false");
950 return;
951 case ELEMENT_NULL:
952 fprintf(fp, "null");
953 return;
954 default:
955 assert(0);
956 }
957 }
958
959 static void
addIndent(FILE * fp,int skip,unsigned indent)960 addIndent(FILE *fp, int skip, unsigned indent)
961 {
962 unsigned sp;
963
964 if (skip) {
965 fprintf(fp, "//");
966 if (indent > 2)
967 for (sp = 0; sp < indent - 2; ++sp)
968 fprintf(fp, " ");
969 } else
970 for (sp = 0; sp < indent; ++sp)
971 fprintf(fp, " ");
972 }
973
974 void
printList(FILE * fp,const struct list * l,isc_boolean_t skip,unsigned indent)975 printList(FILE *fp, const struct list *l, isc_boolean_t skip, unsigned indent)
976 {
977 struct element *elem;
978 struct comment *comment;
979 isc_boolean_t first;
980
981 assert(fp != NULL);
982 assert(l != NULL);
983
984 if (TAILQ_EMPTY(l)) {
985 fprintf(fp, "[ ]");
986 return;
987 }
988
989 fprintf(fp, "[\n");
990 first = ISC_TRUE;
991 TAILQ_FOREACH(elem, l) {
992 isc_boolean_t skip_elem = skip;
993
994 assert(elem->key == NULL);
995 if (!skip) {
996 skip_elem = elem->skip;
997 if (skip_to_end(elem)) {
998 if (!first)
999 fprintf(fp, "\n");
1000 first = ISC_TRUE;
1001 }
1002 }
1003 if (!first)
1004 fprintf(fp, ",\n");
1005 first = ISC_FALSE;
1006 TAILQ_FOREACH(comment, &elem->comments) {
1007 addIndent(fp, skip_elem, indent + 2);
1008 fprintf(fp, "%s\n", comment->line);
1009 }
1010 addIndent(fp, skip_elem, indent + 2);
1011 print(fp, elem, skip_elem, indent + 2);
1012 }
1013 fprintf(fp, "\n");
1014 addIndent(fp, skip, indent);
1015 fprintf(fp, "]");
1016 }
1017
1018 void
printMap(FILE * fp,const struct map * m,isc_boolean_t skip,unsigned indent)1019 printMap(FILE *fp, const struct map *m, isc_boolean_t skip, unsigned indent)
1020 {
1021 struct element *elem;
1022 struct comment *comment;
1023 isc_boolean_t first;
1024
1025 assert(fp != NULL);
1026 assert(m != NULL);
1027
1028 if (TAILQ_EMPTY(m)) {
1029 fprintf(fp, "{ }");
1030 return;
1031 }
1032
1033 fprintf(fp, "{\n");
1034 first = ISC_TRUE;
1035 TAILQ_FOREACH(elem, m) {
1036 isc_boolean_t skip_elem = skip;
1037
1038 assert(elem->key != NULL);
1039 if (!skip) {
1040 skip_elem = elem->skip;
1041 if (skip_to_end(elem)) {
1042 if (!first)
1043 fprintf(fp, "\n");
1044 first = ISC_TRUE;
1045 }
1046 }
1047 if (!first)
1048 fprintf(fp, ",\n");
1049 first = ISC_FALSE;
1050 TAILQ_FOREACH(comment, &elem->comments) {
1051 addIndent(fp, skip_elem, indent + 2);
1052 fprintf(fp, "%s\n", comment->line);
1053 }
1054 addIndent(fp, skip_elem, indent + 2);
1055 fprintf(fp, "\"%s\": ", elem->key);
1056 print(fp, elem, skip_elem, indent + 2);
1057 }
1058 fprintf(fp, "\n");
1059 addIndent(fp, skip, indent);
1060 fprintf(fp, "}");
1061 }
1062
1063 void
printString(FILE * fp,const struct string * s)1064 printString(FILE *fp, const struct string *s)
1065 {
1066 size_t i;
1067
1068 assert(fp != NULL);
1069 assert(s != NULL);
1070
1071 fprintf(fp, "\"");
1072 for (i = 0; i < s->length; i++) {
1073 char c = *(s->content + i);
1074
1075 switch (c) {
1076 case '"':
1077 fprintf(fp, "\\\"");
1078 break;
1079 case '\\':
1080 fprintf(fp, "\\\\");
1081 break;
1082 case '\b':
1083 fprintf(fp, "\\b");
1084 break;
1085 case '\f':
1086 fprintf(fp, "\\f");
1087 break;
1088 case '\n':
1089 fprintf(fp, "\\n");
1090 break;
1091 case '\r':
1092 fprintf(fp, "\\r");
1093 break;
1094 case '\t':
1095 fprintf(fp, "\\t");
1096 break;
1097 default:
1098 if ((c >= 0) && (c < 0x20)) {
1099 fprintf(fp, "\\u%04x", (unsigned)c & 0xff);
1100 } else {
1101 fprintf(fp, "%c", c);
1102 }
1103 }
1104 }
1105 fprintf(fp, "\"");
1106 }
1107
1108 isc_boolean_t
skip_to_end(const struct element * e)1109 skip_to_end(const struct element *e)
1110 {
1111 do {
1112 if (!e->skip)
1113 return ISC_FALSE;
1114 e = TAILQ_NEXT(e);
1115 } while (e != NULL);
1116 return ISC_TRUE;
1117 }
1118
1119 struct element *
copy(struct element * e)1120 copy(struct element *e)
1121 {
1122 struct element *result;
1123 struct comment *comment;
1124
1125 assert(e != NULL);
1126
1127 switch (e->type) {
1128 case ELEMENT_INTEGER:
1129 result = createInt(intValue(e));
1130 break;
1131 case ELEMENT_REAL:
1132 result = createDouble(doubleValue(e));
1133 break;
1134 case ELEMENT_BOOLEAN:
1135 result = createBool(boolValue(e));
1136 break;
1137 case ELEMENT_NULL:
1138 result = createNull();
1139 break;
1140 case ELEMENT_STRING:
1141 result = createString(stringValue(e));
1142 break;
1143 case ELEMENT_LIST:
1144 result = copyList(e);
1145 break;
1146 case ELEMENT_MAP:
1147 result = copyMap(e);
1148 break;
1149 default:
1150 assert(0);
1151 }
1152 result->kind = e->kind;
1153 result->skip = e->skip;
1154 /* don't copy key */
1155 /* copy comments */
1156 TAILQ_FOREACH(comment, &e->comments) {
1157 /* do not reuse comment variable! */
1158 struct comment *tmp;
1159
1160 tmp = createComment(comment->line);
1161 TAILQ_INSERT_TAIL(&result->comments, tmp);
1162 }
1163 return result;
1164 }
1165
1166 struct element *
copyList(struct element * l)1167 copyList(struct element *l)
1168 {
1169 struct element *result;
1170 size_t i;
1171
1172 result = createList();
1173 for (i = 0; i < listSize(l); i++)
1174 listPush(result, copy(listGet(l, i)));
1175 return result;
1176 }
1177
1178 struct element *
copyMap(struct element * m)1179 copyMap(struct element *m)
1180 {
1181 struct element *result;
1182 struct element *item;
1183
1184 result = createMap();
1185 TAILQ_FOREACH(item, &m->value.map_value)
1186 mapSet(result, copy(item), item->key);
1187 return result;
1188 }
1189
1190 struct handle *
mapPop(struct element * m)1191 mapPop(struct element *m)
1192 {
1193 struct element *item;
1194 struct handle *h;
1195
1196 assert(m != NULL);
1197 assert(m->type == ELEMENT_MAP);
1198
1199 h = (struct handle *)malloc(sizeof(struct handle));
1200 assert(h != NULL);
1201 memset(h, 0, sizeof(struct handle));
1202 TAILQ_INIT(&h->values);
1203
1204 item = TAILQ_FIRST(&m->value.map_value);
1205 assert(item != NULL);
1206 assert(item->key != NULL);
1207 h->key = strdup(item->key);
1208 assert(h->key != NULL);
1209 h->value = item;
1210
1211 TAILQ_REMOVE(&m->value.map_value, item);
1212
1213 return h;
1214 }
1215
1216 void
derive(struct handle * src,struct handle * dst)1217 derive(struct handle *src, struct handle *dst)
1218 {
1219 struct element *list;
1220 struct element *item;
1221 size_t i;
1222
1223 if (dst == NULL)
1224 return;
1225 list = dst->value;
1226 assert(list != NULL);
1227 assert(list->type == ELEMENT_LIST);
1228 for (i = 0; i < listSize(list); i++) {
1229 item = listGet(list, i);
1230 assert(item != NULL);
1231 assert(item->type == ELEMENT_MAP);
1232 if (mapContains(item, src->key))
1233 continue;
1234 mapSet(item, copy(src->value), src->key);
1235 }
1236 }
1237
1238 struct string *
hexaValue(struct element * s)1239 hexaValue(struct element *s)
1240 {
1241 struct string *h;
1242
1243 assert(s != NULL);
1244 assert(s->type == ELEMENT_STRING);
1245
1246 h = stringValue(s);
1247 assert(h->length >= 2);
1248
1249 /* string leading 0x */
1250 return makeString(h->length - 2, h->content + 2);
1251 }
1252
1253 struct element *
createHexa(struct string * h)1254 createHexa(struct string *h)
1255 {
1256 struct string *s;
1257
1258 assert(h != NULL);
1259
1260 s = makeString(-1, "0x");
1261 concatString(s, h);
1262 return createString(s);
1263 }
1264