1 /*  Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #include <stdio.h>
18 
19 #include "libknot/yparser/yptrafo.h"
20 #include "libknot/attribute.h"
21 #include "libknot/errcode.h"
22 
format_item(const yp_item_t * item,const uint8_t * data,size_t data_len,char * out,size_t out_len,yp_style_t style,const char * prefix,bool first_value,bool last_value)23 static int format_item(
24 	const yp_item_t *item,
25 	const uint8_t *data,
26 	size_t data_len,
27 	char *out,
28 	size_t out_len,
29 	yp_style_t style,
30 	const char *prefix,
31 	bool first_value,
32 	bool last_value)
33 {
34 	if (item == NULL || out == NULL || prefix == NULL) {
35 		return KNOT_EINVAL;
36 	}
37 
38 	// Format key part.
39 	int ret = snprintf(out, out_len, "%s%s%s%s",
40 	                   first_value ? prefix : "",
41 	                   first_value ? item->name + 1 : "",
42 	                   first_value ? ":" : "",
43 	                   item->type == YP_TGRP ?
44 	                     "\n" : (first_value && !last_value ? " [ " : " "));
45 	if (ret < 0 || ret >= out_len) {
46 		return KNOT_ESPACE;
47 	}
48 	out     += ret;
49 	out_len -= ret;
50 
51 	// Finish if group.
52 	if (item->type == YP_TGRP) {
53 		return KNOT_EOK;
54 	}
55 
56 	// Format data part.
57 	size_t aux_len = out_len;
58 	ret = yp_item_to_txt(item, data, data_len, out, &aux_len, style);
59 	if (ret != KNOT_EOK) {
60 		return ret;
61 	}
62 	out     += aux_len;
63 	out_len -= aux_len;
64 
65 	// Format data end.
66 	ret = snprintf(out, out_len, "%s%s",
67 	               last_value && !first_value ? " ]" : "",
68 	               last_value ? "\n" : ",");
69 	if (ret < 0 || ret >= out_len) {
70 		return KNOT_ESPACE;
71 	}
72 
73 	return KNOT_EOK;
74 }
75 
76 _public_
yp_format_key0(const yp_item_t * item,const uint8_t * data,size_t data_len,char * out,size_t out_len,yp_style_t style,bool first_value,bool last_value)77 int yp_format_key0(
78 	const yp_item_t *item,
79 	const uint8_t *data,
80 	size_t data_len,
81 	char *out,
82 	size_t out_len,
83 	yp_style_t style,
84 	bool first_value,
85 	bool last_value)
86 {
87 	return format_item(item, data, data_len, out, out_len, style, "",
88 	                   first_value, last_value);
89 }
90 
91 _public_
yp_format_id(const yp_item_t * item,const uint8_t * data,size_t data_len,char * out,size_t out_len,yp_style_t style)92 int yp_format_id(
93 	const yp_item_t *item,
94 	const uint8_t *data,
95 	size_t data_len,
96 	char *out,
97 	size_t out_len,
98 	yp_style_t style)
99 {
100 	if (data == NULL) {
101 		return KNOT_EINVAL;
102 	}
103 
104 	return format_item(item, data, data_len, out, out_len, style, "  - ",
105 	                   true, true);
106 }
107 
108 _public_
yp_format_key1(const yp_item_t * item,const uint8_t * data,size_t data_len,char * out,size_t out_len,yp_style_t style,bool first_value,bool last_value)109 int yp_format_key1(
110 	const yp_item_t *item,
111 	const uint8_t *data,
112 	size_t data_len,
113 	char *out,
114 	size_t out_len,
115 	yp_style_t style,
116 	bool first_value,
117 	bool last_value)
118 {
119 	return format_item(item, data, data_len, out, out_len, style, "    ",
120 	                   first_value, last_value);
121 }
122