]> git.proxmox.com Git - mirror_iproute2.git/blob - lib/json_print.c
iproute: Set ip/ip6 lwtunnel flags
[mirror_iproute2.git] / lib / json_print.c
1 /*
2 * json_print.c "print regular or json output, based on json_writer".
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Julien Fortin, <julien@cumulusnetworks.com>
10 */
11
12 #include <stdarg.h>
13 #include <stdio.h>
14
15 #include "utils.h"
16 #include "json_print.h"
17
18 static json_writer_t *_jw;
19
20 #define _IS_JSON_CONTEXT(type) ((type & PRINT_JSON || type & PRINT_ANY) && _jw)
21 #define _IS_FP_CONTEXT(type) (!_jw && (type & PRINT_FP || type & PRINT_ANY))
22
23 void new_json_obj(int json)
24 {
25 if (json) {
26 _jw = jsonw_new(stdout);
27 if (!_jw) {
28 perror("json object");
29 exit(1);
30 }
31 if (pretty)
32 jsonw_pretty(_jw, true);
33 jsonw_start_array(_jw);
34 }
35 }
36
37 void delete_json_obj(void)
38 {
39 if (_jw) {
40 jsonw_end_array(_jw);
41 jsonw_destroy(&_jw);
42 }
43 }
44
45 bool is_json_context(void)
46 {
47 return _jw != NULL;
48 }
49
50 json_writer_t *get_json_writer(void)
51 {
52 return _jw;
53 }
54
55 void open_json_object(const char *str)
56 {
57 if (_IS_JSON_CONTEXT(PRINT_JSON)) {
58 if (str)
59 jsonw_name(_jw, str);
60 jsonw_start_object(_jw);
61 }
62 }
63
64 void close_json_object(void)
65 {
66 if (_IS_JSON_CONTEXT(PRINT_JSON))
67 jsonw_end_object(_jw);
68 }
69
70 /*
71 * Start json array or string array using
72 * the provided string as json key (if not null)
73 * or as array delimiter in non-json context.
74 */
75 void open_json_array(enum output_type type, const char *str)
76 {
77 if (_IS_JSON_CONTEXT(type)) {
78 if (str)
79 jsonw_name(_jw, str);
80 jsonw_start_array(_jw);
81 } else if (_IS_FP_CONTEXT(type)) {
82 printf("%s", str);
83 }
84 }
85
86 /*
87 * End json array or string array
88 */
89 void close_json_array(enum output_type type, const char *str)
90 {
91 if (_IS_JSON_CONTEXT(type)) {
92 jsonw_end_array(_jw);
93 } else if (_IS_FP_CONTEXT(type)) {
94 printf("%s", str);
95 }
96 }
97
98 /*
99 * pre-processor directive to generate similar
100 * functions handling different types
101 */
102 #define _PRINT_FUNC(type_name, type) \
103 __attribute__((format(printf, 4, 0))) \
104 void print_color_##type_name(enum output_type t, \
105 enum color_attr color, \
106 const char *key, \
107 const char *fmt, \
108 type value) \
109 { \
110 if (_IS_JSON_CONTEXT(t)) { \
111 if (!key) \
112 jsonw_##type_name(_jw, value); \
113 else \
114 jsonw_##type_name##_field(_jw, key, value); \
115 } else if (_IS_FP_CONTEXT(t)) { \
116 color_fprintf(stdout, color, fmt, value); \
117 } \
118 }
119 _PRINT_FUNC(int, int);
120 _PRINT_FUNC(s64, int64_t);
121 _PRINT_FUNC(hhu, unsigned char);
122 _PRINT_FUNC(hu, unsigned short);
123 _PRINT_FUNC(uint, unsigned int);
124 _PRINT_FUNC(u64, uint64_t);
125 _PRINT_FUNC(luint, unsigned long);
126 _PRINT_FUNC(lluint, unsigned long long);
127 _PRINT_FUNC(float, double);
128 #undef _PRINT_FUNC
129
130 void print_color_string(enum output_type type,
131 enum color_attr color,
132 const char *key,
133 const char *fmt,
134 const char *value)
135 {
136 if (_IS_JSON_CONTEXT(type)) {
137 if (key && !value)
138 jsonw_name(_jw, key);
139 else if (!key && value)
140 jsonw_string(_jw, value);
141 else
142 jsonw_string_field(_jw, key, value);
143 } else if (_IS_FP_CONTEXT(type)) {
144 color_fprintf(stdout, color, fmt, value);
145 }
146 }
147
148 /*
149 * value's type is bool. When using this function in FP context you can't pass
150 * a value to it, you will need to use "is_json_context()" to have different
151 * branch for json and regular output. grep -r "print_bool" for example
152 */
153 void print_color_bool(enum output_type type,
154 enum color_attr color,
155 const char *key,
156 const char *fmt,
157 bool value)
158 {
159 if (_IS_JSON_CONTEXT(type)) {
160 if (key)
161 jsonw_bool_field(_jw, key, value);
162 else
163 jsonw_bool(_jw, value);
164 } else if (_IS_FP_CONTEXT(type)) {
165 color_fprintf(stdout, color, fmt, value ? "true" : "false");
166 }
167 }
168
169 /*
170 * In JSON context uses hardcode %#x format: 42 -> 0x2a
171 */
172 void print_color_0xhex(enum output_type type,
173 enum color_attr color,
174 const char *key,
175 const char *fmt,
176 unsigned long long hex)
177 {
178 if (_IS_JSON_CONTEXT(type)) {
179 SPRINT_BUF(b1);
180
181 snprintf(b1, sizeof(b1), "%#llx", hex);
182 print_string(PRINT_JSON, key, NULL, b1);
183 } else if (_IS_FP_CONTEXT(type)) {
184 color_fprintf(stdout, color, fmt, hex);
185 }
186 }
187
188 void print_color_hex(enum output_type type,
189 enum color_attr color,
190 const char *key,
191 const char *fmt,
192 unsigned int hex)
193 {
194 if (_IS_JSON_CONTEXT(type)) {
195 SPRINT_BUF(b1);
196
197 snprintf(b1, sizeof(b1), "%x", hex);
198 if (key)
199 jsonw_string_field(_jw, key, b1);
200 else
201 jsonw_string(_jw, b1);
202 } else if (_IS_FP_CONTEXT(type)) {
203 color_fprintf(stdout, color, fmt, hex);
204 }
205 }
206
207 /*
208 * In JSON context we don't use the argument "value" we simply call jsonw_null
209 * whereas FP context can use "value" to output anything
210 */
211 void print_color_null(enum output_type type,
212 enum color_attr color,
213 const char *key,
214 const char *fmt,
215 const char *value)
216 {
217 if (_IS_JSON_CONTEXT(type)) {
218 if (key)
219 jsonw_null_field(_jw, key);
220 else
221 jsonw_null(_jw);
222 } else if (_IS_FP_CONTEXT(type)) {
223 color_fprintf(stdout, color, fmt, value);
224 }
225 }
226
227 /* Print line seperator (if not in JSON mode) */
228 void print_nl(void)
229 {
230 if (!_jw)
231 printf("%s", _SL_);
232 }