Fixed issue with json output in vpp_api_test.
[vpp.git] / vpp-api-test / vat / json_format.h
1 /*
2  *------------------------------------------------------------------
3  * json_format.h
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 #ifndef __JSON_FORMAT_H__
21 #define __JSON_FORMAT_H__
22
23 #include <vppinfra/clib.h>
24 #include <vppinfra/format.h>
25 #include <netinet/ip.h>
26
27 /* JSON value type */
28 typedef enum {
29     VAT_JSON_NONE,
30     VAT_JSON_OBJECT,
31     VAT_JSON_ARRAY,
32     VAT_JSON_STRING,
33     VAT_JSON_REAL,
34     VAT_JSON_UINT,
35     VAT_JSON_INT,
36     VAT_JSON_IPV4,
37     VAT_JSON_IPV6,
38     VAT_JSON_MAX
39 } vat_json_val_type_t;
40
41 typedef struct vat_json_node_s vat_json_node_t;
42 typedef struct vat_json_pair_s vat_json_pair_t;
43
44 /* JSON object structure */
45 struct vat_json_node_s {
46     vat_json_val_type_t type;
47     union {
48         vat_json_pair_t * pairs;
49         vat_json_node_t * array;
50         u8 * string;
51         struct in_addr ip4;
52         struct in6_addr ip6;
53         u64 uint;
54         i64 sint;
55         f64 real;
56     };
57 };
58
59 struct vat_json_pair_s {
60     const char *name;
61     vat_json_node_t value;
62 };
63
64 void vat_json_print(FILE *ofp, vat_json_node_t *node);
65 void vat_json_free(vat_json_node_t *node);
66
67 static_always_inline void vat_json_init_object(vat_json_node_t *json)
68 {
69     json->type = VAT_JSON_OBJECT;
70     json->pairs = NULL;
71 }
72
73 static_always_inline void vat_json_init_array(vat_json_node_t *json)
74 {
75     json->type = VAT_JSON_ARRAY;
76     json->array = NULL;
77 }
78
79 static_always_inline void vat_json_set_string(vat_json_node_t *json, u8 *str)
80 {
81     json->type = VAT_JSON_STRING;
82     json->string = str;
83 }
84
85 static_always_inline void vat_json_set_string_copy(vat_json_node_t *json,
86                                                    const u8 *str)
87 {
88     u8 * ns = NULL;
89     vec_validate(ns, strlen((const char *)str));
90     strcpy((char*)ns, (const char*)str);
91     vec_add1(ns, '\0');
92     vat_json_set_string(json, ns);
93 }
94
95 static_always_inline void vat_json_set_int(vat_json_node_t *json, i64 num)
96 {
97     json->type = VAT_JSON_INT;
98     json->sint = num;
99 }
100
101 static_always_inline void vat_json_set_uint(vat_json_node_t *json, u64 num)
102 {
103     json->type = VAT_JSON_UINT;
104     json->uint = num;
105 }
106
107 static_always_inline void vat_json_set_real(vat_json_node_t *json, f64 real)
108 {
109     json->type = VAT_JSON_REAL;
110     json->real = real;
111 }
112
113 static_always_inline void vat_json_set_ip4(vat_json_node_t *json,
114                                            struct in_addr ip4)
115 {
116     json->type = VAT_JSON_IPV4;
117     json->ip4 = ip4;
118 }
119
120 static_always_inline void vat_json_set_ip6(vat_json_node_t *json,
121                                            struct in6_addr ip6)
122 {
123     json->type = VAT_JSON_IPV6;
124     json->ip6 = ip6;
125 }
126
127 static_always_inline vat_json_node_t* vat_json_object_add(vat_json_node_t *json,
128                                                           const char *name)
129 {
130     ASSERT(VAT_JSON_OBJECT == json->type);
131     uword pos = vec_len(json->pairs);
132     vec_validate(json->pairs, pos);
133     json->pairs[pos].name = name;
134     return &json->pairs[pos].value;
135 }
136
137 static_always_inline vat_json_node_t* vat_json_array_add(vat_json_node_t *json)
138 {
139     ASSERT(VAT_JSON_ARRAY == json->type);
140     uword pos = vec_len(json->array);
141     vec_validate(json->array, pos);
142     return &json->array[pos];
143 }
144
145 static_always_inline vat_json_node_t* vat_json_object_add_list(vat_json_node_t *json,
146                                                                const char *name)
147 {
148     vat_json_node_t *array_node = vat_json_object_add(json, name);
149     vat_json_init_array(array_node);
150     return array_node;
151 }
152
153 static_always_inline void vat_json_object_add_string_copy(vat_json_node_t *json,
154                                                           const char *name,
155                                                           u8 *str)
156 {
157     vat_json_set_string_copy(vat_json_object_add(json, name), str);
158 }
159
160 static_always_inline void vat_json_object_add_uint(vat_json_node_t *json,
161                                                      const char *name,
162                                                      u64 number)
163 {
164     vat_json_set_uint(vat_json_object_add(json, name), number);
165 }
166
167 static_always_inline void vat_json_object_add_int(vat_json_node_t *json,
168                                                      const char *name,
169                                                      i64 number)
170 {
171     vat_json_set_int(vat_json_object_add(json, name), number);
172 }
173
174 static_always_inline void vat_json_object_add_real(vat_json_node_t *json,
175                                                    const char *name, f64 real)
176 {
177     vat_json_set_real(vat_json_object_add(json, name), real);
178 }
179
180 static_always_inline void vat_json_object_add_ip4(vat_json_node_t *json,
181                                                   const char *name,
182                                                   struct in_addr ip4)
183 {
184     vat_json_set_ip4(vat_json_object_add(json, name), ip4);
185 }
186
187 static_always_inline void vat_json_object_add_ip6(vat_json_node_t *json,
188                                                   const char *name,
189                                                   struct in6_addr ip6)
190 {
191     vat_json_set_ip6(vat_json_object_add(json, name), ip6);
192 }
193
194 static_always_inline void vat_json_array_add_int(vat_json_node_t *json,
195                                                  i64 number)
196 {
197     vat_json_set_int(vat_json_array_add(json), number);
198 }
199
200 static_always_inline void vat_json_array_add_uint(vat_json_node_t *json,
201                                                   u64 number)
202 {
203     vat_json_set_uint(vat_json_array_add(json), number);
204 }
205
206 static_always_inline void vat_json_object_add_bytes(vat_json_node_t *json,
207                                                     const char *name,
208                                                     u8 *array, uword size)
209 {
210     ASSERT(VAT_JSON_OBJECT == json->type);
211     vat_json_node_t *json_array = vat_json_object_add(json, name);
212     vat_json_init_array(json_array);
213     int i;
214     for (i = 0; i < size; i++) {
215         vat_json_array_add_uint(json_array, array[i]);
216     }
217 }
218
219 static_always_inline vat_json_node_t*
220 vat_json_object_get_element(vat_json_node_t *json, const char *name)
221 {
222     int i = 0;
223
224     ASSERT(VAT_JSON_OBJECT == json->type);
225     for (i = 0; i < vec_len(json->pairs); i++) {
226         if (0 == strcmp(json->pairs[i].name, name)) {
227             return &json->pairs[i].value;
228         }
229     }
230     return NULL;
231 }
232
233 #endif /* __JSON_FORMAT_H__ */