1 /* $NetBSD: data.c,v 1.2 2020/08/03 21:10:57 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2017 by 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 * 950 Charter Street 20 * Redwood City, CA 94063 21 * <info@isc.org> 22 * http://www.isc.org/ 23 */ 24 25 #include <sys/cdefs.h> 26 __RCSID("$NetBSD: data.c,v 1.2 2020/08/03 21:10:57 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