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