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