Home | History | Annotate | Line # | Download | only in keama
      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 (at) 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 *
     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 *
     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 *
     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 *
    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
    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
    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
    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 *
    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 *
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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
    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 
    571 void resetNull(struct element *e)
    572 {
    573 	assert(e != NULL);
    574 
    575 	reset(e);
    576 	e->type = ELEMENT_NULL;
    577 }
    578 
    579 void
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
   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
   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
   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 *
   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 *
   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 *
   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 *
   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
   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 *
   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 *
   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