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