xref: /netbsd-src/external/mpl/dhcp/dist/keama/data.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
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