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