blob: 6f316d972ebcf4576ce8c1618807cd5e67114f7b [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 *------------------------------------------------------------------
3 * json_format.c
4 *
5 * Copyright (c) 2015 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18
19*/
20#include <inttypes.h>
21#include <vat/json_format.h>
22#include <vnet/ip/ip.h>
23#include <vppinfra/vec.h>
24
25#define VAT_TAB_WIDTH 2
26
Dave Barach72d72232016-08-04 10:15:08 -040027typedef struct vat_print_ctx_s
28{
29 FILE *ofp;
30 u32 indent;
Ed Warnickecb9cada2015-12-08 15:45:58 -070031} vat_print_ctx_t;
32
33/* Format an IP4 address. */
Dave Barach72d72232016-08-04 10:15:08 -040034static u8 *
35vat_json_format_ip4_address (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070036{
Dave Barach72d72232016-08-04 10:15:08 -040037 u8 *a = va_arg (*args, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070038 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
39}
40
41/* Format an IP6 address. */
Dave Barach72d72232016-08-04 10:15:08 -040042static u8 *
43vat_json_format_ip6_address (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070044{
Dave Barach72d72232016-08-04 10:15:08 -040045 ip6_address_t *a = va_arg (*args, ip6_address_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070046 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
47
48 i_max_n_zero = ARRAY_LEN (a->as_u16);
49 max_n_zeros = 0;
50 i_first_zero = i_max_n_zero;
51 n_zeros = 0;
52 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
53 {
54 u32 is_zero = a->as_u16[i] == 0;
55 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
Dave Barach72d72232016-08-04 10:15:08 -040056 {
57 i_first_zero = i;
58 n_zeros = 0;
59 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070060 n_zeros += is_zero;
Dave Barach72d72232016-08-04 10:15:08 -040061 if ((!is_zero && n_zeros > max_n_zeros)
62 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
63 {
64 i_max_n_zero = i_first_zero;
65 max_n_zeros = n_zeros;
66 i_first_zero = ARRAY_LEN (a->as_u16);
67 n_zeros = 0;
68 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070069 }
70
71 last_double_colon = 0;
72 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
73 {
74 if (i == i_max_n_zero && max_n_zeros > 1)
Dave Barach72d72232016-08-04 10:15:08 -040075 {
76 s = format (s, "::");
77 i += max_n_zeros - 1;
78 last_double_colon = 1;
79 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070080 else
Dave Barach72d72232016-08-04 10:15:08 -040081 {
82 s = format (s, "%s%x",
83 (last_double_colon || i == 0) ? "" : ":",
84 clib_net_to_host_u16 (a->as_u16[i]));
85 last_double_colon = 0;
86 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 }
88
89 return s;
90}
91
92static void
Dave Barach72d72232016-08-04 10:15:08 -040093vat_json_indent_print (vat_print_ctx_t * ctx)
Ed Warnickecb9cada2015-12-08 15:45:58 -070094{
Dave Barach72d72232016-08-04 10:15:08 -040095 int i;
96 for (i = 0; i < ctx->indent * VAT_TAB_WIDTH; i++)
97 {
98 fformat (ctx->ofp, " ");
Ed Warnickecb9cada2015-12-08 15:45:58 -070099 }
100}
101
102static void
Dave Barach72d72232016-08-04 10:15:08 -0400103vat_json_indent_line (vat_print_ctx_t * ctx, char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104{
Dave Barach72d72232016-08-04 10:15:08 -0400105 va_list va;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106
Dave Barach72d72232016-08-04 10:15:08 -0400107 vat_json_indent_print (ctx);
108 va_start (va, fmt);
109 va_fformat (ctx->ofp, fmt, &va);
110 va_end (va);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111}
112
113static u8
114is_num_only (vat_json_node_t * p)
115{
Dave Barach72d72232016-08-04 10:15:08 -0400116 vat_json_node_t *elem;
117 vec_foreach (elem, p)
118 {
119 if (VAT_JSON_INT != elem->type && VAT_JSON_UINT != elem->type)
120 {
121 return 0;
122 }
123 }
124 return 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125}
126
127static void
Dave Barach72d72232016-08-04 10:15:08 -0400128vat_json_print_internal (vat_print_ctx_t * ctx, vat_json_node_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129{
130#define P(fmt,...) fformat(ctx->ofp, fmt, ##__VA_ARGS__)
131#define PL(fmt,...) fformat(ctx->ofp, fmt"\n", ##__VA_ARGS__)
132#define PPL(fmt,...) vat_json_indent_line(ctx, fmt"\n", ##__VA_ARGS__)
133#define PP(fmt,...) vat_json_indent_line(ctx, fmt, ##__VA_ARGS__)
134#define INCR (ctx->indent++)
135#define DECR (ctx->indent--)
136
Dave Barach72d72232016-08-04 10:15:08 -0400137 vat_json_pair_t *pair;
138 u32 i, count;
139 vat_json_node_t *elem;
140 u8 num_only = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141
Dave Barach72d72232016-08-04 10:15:08 -0400142 if (!node)
143 {
144 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700145 }
146
Dave Barach72d72232016-08-04 10:15:08 -0400147 switch (node->type)
148 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149 case VAT_JSON_OBJECT:
Dave Barach72d72232016-08-04 10:15:08 -0400150 count = vec_len (node->pairs);
151 if (count >= 1)
152 {
153 PL ("{");
154 INCR;
155 for (i = 0; i < count; i++)
156 {
157 pair = &node->pairs[i];
158 PP ("\"%s\": ", pair->name);
159 vat_json_print_internal (ctx, &pair->value);
160 if (i < count - 1)
161 {
162 P (",");
163 }
164 PL ();
165 }
166 DECR;
167 PP ("}");
168 }
169 else
170 {
171 P ("{}");
172 }
173 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174 case VAT_JSON_ARRAY:
Dave Barach72d72232016-08-04 10:15:08 -0400175 num_only = is_num_only (node->array);
176 count = vec_len (node->array);
177 if (count >= 1)
178 {
179 if (num_only)
180 P ("[");
181 else
182 PL ("[ ");
183 INCR;
184 for (i = 0; i < count; i++)
185 {
186 elem = &node->array[i];
187 if (!num_only)
188 {
189 vat_json_indent_print (ctx);
190 }
191 vat_json_print_internal (ctx, elem);
192 if (i < count - 1)
193 {
194 if (num_only)
195 {
196 P (", ");
197 }
198 else
199 {
200 P (",");
201 }
202 }
203 if (!num_only)
204 PL ();
205 }
206 DECR;
207 if (!num_only)
208 PP ("]");
209 else
210 P ("]");
211 }
212 else
213 {
214 P ("[]");
215 }
216 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217 case VAT_JSON_INT:
Dave Barach72d72232016-08-04 10:15:08 -0400218 P ("%d", node->sint);
219 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700220 case VAT_JSON_UINT:
Dave Barach72d72232016-08-04 10:15:08 -0400221 P ("%" PRIu64, node->uint);
222 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 case VAT_JSON_REAL:
Dave Barach72d72232016-08-04 10:15:08 -0400224 P ("%f", node->real);
225 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700226 case VAT_JSON_STRING:
Dave Barach72d72232016-08-04 10:15:08 -0400227 P ("\"%s\"", node->string);
228 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229 case VAT_JSON_IPV4:
Dave Barach72d72232016-08-04 10:15:08 -0400230 P ("\"%U\"", vat_json_format_ip4_address, &node->ip4);
231 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232 case VAT_JSON_IPV6:
Dave Barach72d72232016-08-04 10:15:08 -0400233 P ("\"%U\"", vat_json_format_ip6_address, &node->ip6);
234 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235 default:
Dave Barach72d72232016-08-04 10:15:08 -0400236 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237 }
238#undef PPL
239#undef PP
240#undef PL
241#undef P
242}
243
Dave Barach72d72232016-08-04 10:15:08 -0400244void
245vat_json_print (FILE * ofp, vat_json_node_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700246{
Dave Barach72d72232016-08-04 10:15:08 -0400247 vat_print_ctx_t ctx;
248 memset (&ctx, 0, sizeof ctx);
249 ctx.indent = 0;
250 ctx.ofp = ofp;
251 fformat (ofp, "\n");
252 vat_json_print_internal (&ctx, node);
253 fformat (ofp, "\n");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254}
255
Dave Barach72d72232016-08-04 10:15:08 -0400256void
257vat_json_free (vat_json_node_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258{
Dave Barach72d72232016-08-04 10:15:08 -0400259 int i = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260
Dave Barach72d72232016-08-04 10:15:08 -0400261 if (NULL == node)
262 {
263 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264 }
Dave Barach72d72232016-08-04 10:15:08 -0400265 switch (node->type)
266 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267 case VAT_JSON_OBJECT:
Dave Barach72d72232016-08-04 10:15:08 -0400268 for (i = 0; i < vec_len (node->pairs); i++)
269 {
270 vat_json_free (&node->pairs[i].value);
271 }
272 if (NULL != node->pairs)
273 {
274 vec_free (node->pairs);
275 }
276 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 case VAT_JSON_ARRAY:
Dave Barach72d72232016-08-04 10:15:08 -0400278 for (i = 0; i < vec_len (node->array); i++)
279 {
280 vat_json_free (&node->array[i]);
281 }
282 if (NULL != node->array)
283 {
284 vec_free (node->array);
285 }
286 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287 case VAT_JSON_STRING:
Dave Barach72d72232016-08-04 10:15:08 -0400288 if (NULL != node->string)
289 {
290 vec_free (node->string);
291 }
292 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293 default:
Dave Barach72d72232016-08-04 10:15:08 -0400294 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700295 }
296}
Dave Barach72d72232016-08-04 10:15:08 -0400297
298/*
299 * fd.io coding-style-patch-verification: ON
300 *
301 * Local Variables:
302 * eval: (c-set-style "gnu")
303 * End:
304 */