2 *------------------------------------------------------------------
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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
21 #include <vat/json_format.h>
22 #include <vnet/ip/ip.h>
23 #include <vppinfra/vec.h>
25 #define VAT_TAB_WIDTH 2
27 typedef struct vat_print_ctx_s {
32 /* Format an IP4 address. */
33 static u8 * vat_json_format_ip4_address (u8 * s, va_list * args)
35 u8 * a = va_arg (*args, u8 *);
36 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
39 /* Format an IP6 address. */
40 static u8 * vat_json_format_ip6_address (u8 * s, va_list * args)
42 ip6_address_t * a = va_arg (*args, ip6_address_t *);
43 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
45 i_max_n_zero = ARRAY_LEN (a->as_u16);
47 i_first_zero = i_max_n_zero;
49 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
51 u32 is_zero = a->as_u16[i] == 0;
52 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
58 if ((! is_zero && n_zeros > max_n_zeros)
59 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
61 i_max_n_zero = i_first_zero;
62 max_n_zeros = n_zeros;
63 i_first_zero = ARRAY_LEN (a->as_u16);
68 last_double_colon = 0;
69 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
71 if (i == i_max_n_zero && max_n_zeros > 1)
75 last_double_colon = 1;
79 s = format (s, "%s%x",
80 (last_double_colon || i == 0) ? "" : ":",
81 clib_net_to_host_u16 (a->as_u16[i]));
82 last_double_colon = 0;
90 vat_json_indent_print (vat_print_ctx_t *ctx)
93 for (i=0; i<ctx->indent * VAT_TAB_WIDTH; i++) {
94 fformat(ctx->ofp, " ");
99 vat_json_indent_line (vat_print_ctx_t * ctx, char * fmt, ...)
103 vat_json_indent_print(ctx);
105 va_fformat(ctx->ofp, fmt, &va);
110 is_num_only (vat_json_node_t * p)
112 vat_json_node_t * elem;
113 vec_foreach(elem, p) {
114 if (VAT_JSON_INT != elem->type &&
115 VAT_JSON_UINT != elem->type) {
123 vat_json_print_internal (vat_print_ctx_t *ctx, vat_json_node_t *node)
125 #define P(fmt,...) fformat(ctx->ofp, fmt, ##__VA_ARGS__)
126 #define PL(fmt,...) fformat(ctx->ofp, fmt"\n", ##__VA_ARGS__)
127 #define PPL(fmt,...) vat_json_indent_line(ctx, fmt"\n", ##__VA_ARGS__)
128 #define PP(fmt,...) vat_json_indent_line(ctx, fmt, ##__VA_ARGS__)
129 #define INCR (ctx->indent++)
130 #define DECR (ctx->indent--)
132 vat_json_pair_t *pair;
134 vat_json_node_t *elem;
141 switch (node->type) {
142 case VAT_JSON_OBJECT:
143 count = vec_len(node->pairs);
147 for (i=0; i<count; i++) {
148 pair = &node->pairs[i];
149 PP("\"%s\": ", pair->name);
150 vat_json_print_internal(ctx, &pair->value);
161 num_only = is_num_only(node->array);
162 count = vec_len(node->array);
169 for (i=0; i<count; i++) {
170 elem = &node->array[i];
172 vat_json_indent_print(ctx);
174 vat_json_print_internal(ctx, elem);
195 P("%"PRIu64, node->uint);
200 case VAT_JSON_STRING:
201 P("\"%s\"", node->string);
204 P("\"%U\"", vat_json_format_ip4_address, &node->ip4);
207 P("\"%U\"", vat_json_format_ip6_address, &node->ip6);
218 void vat_json_print(FILE *ofp, vat_json_node_t *node)
221 memset(&ctx, 0, sizeof ctx);
225 vat_json_print_internal(&ctx, node);
229 void vat_json_free (vat_json_node_t *node)
236 switch (node->type) {
237 case VAT_JSON_OBJECT:
238 for (i = 0; i < vec_len(node->pairs); i++) {
239 vat_json_free(&node->pairs[i].value);
241 if (NULL != node->pairs) {
242 vec_free(node->pairs);
246 for (i = 0; i < vec_len(node->array); i++) {
247 vat_json_free(&node->array[i]);
249 if (NULL != node->array) {
250 vec_free(node->array);
253 case VAT_JSON_STRING:
254 if (NULL != node->string) {
255 vec_free(node->string);