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 36struct string * 37allocString(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 48struct string * 49makeString(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 68struct string * 69makeStringExt(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 272struct string * 273makeStringArray(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 315void 316appendString(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 334void 335concatString(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 347isc_boolean_t 348eqString(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 360struct string * 361quote(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 371struct comment * 372createComment(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 387int64_t 388intValue(const struct element *e) 389{ 390 assert(e != NULL); 391 assert(e->type == ELEMENT_INTEGER); 392 return e->value.int_value; 393} 394 395double 396doubleValue(const struct element *e) 397{ 398 assert(e != NULL); 399 assert(e->type == ELEMENT_REAL); 400 return e->value.double_value; 401} 402 403isc_boolean_t 404boolValue(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 412struct string * 413stringValue(struct element *e) 414{ 415 assert(e != NULL); 416 assert(e->type == ELEMENT_STRING); 417 return &e->value.string_value; 418} 419 420struct list * 421listValue(struct element *e) 422{ 423 assert(e != NULL); 424 assert(e->type == ELEMENT_LIST); 425 return &e->value.list_value; 426} 427 428struct map * 429mapValue(struct element *e) 430{ 431 assert(e != NULL); 432 assert(e->type == ELEMENT_MAP); 433 return &e->value.map_value; 434} 435 436struct element * 437create(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 449struct element * 450createInt(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 461struct element * 462createDouble(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 473struct element * 474createBool(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 485struct element * 486createNull(void) 487{ 488 struct element *elem; 489 490 elem = create(); 491 elem->type = ELEMENT_NULL; 492 493 return elem; 494} 495 496struct element * 497createString(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 508struct element * 509createList(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 520struct element * 521createMap(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 532static void 533reset(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 541void 542resetInt(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 551void 552resetDouble(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 561void 562resetBool(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 571void resetNull(struct element *e) 572{ 573 assert(e != NULL); 574 575 reset(e); 576 e->type = ELEMENT_NULL; 577} 578 579void 580resetString(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 589void 590resetList(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 599void 600resetMap(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 609void 610resetBy(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 650struct element * 651listGet(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 673void 674listSet(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 701void 702listPush(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 711void 712listRemove(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 734size_t 735listSize(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 752void 753concat(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 763struct element * 764mapGet(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 781void 782mapSet(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 796void 797mapRemove(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 815isc_boolean_t 816mapContains(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 833size_t 834mapSize(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 851void 852merge(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 871const char * 872type2name(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 899int 900name2type(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 923void 924print(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 959static void 960addIndent(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 974void 975printList(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 1018void 1019printMap(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 1063void 1064printString(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 1108isc_boolean_t 1109skip_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 1119struct element * 1120copy(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 1166struct element * 1167copyList(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 1178struct element * 1179copyMap(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 1190struct handle * 1191mapPop(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 1216void 1217derive(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 1238struct string * 1239hexaValue(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 1253struct element * 1254createHexa(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