1
2
3
4
5
6
7
8
9
10
11
12#include <stdarg.h>
13#include <stdio.h>
14
15#include "utils.h"
16#include "json_print.h"
17
18static json_writer_t *_jw;
19
20static void __new_json_obj(int json, bool have_array)
21{
22 if (json) {
23 _jw = jsonw_new(stdout);
24 if (!_jw) {
25 perror("json object");
26 exit(1);
27 }
28 if (pretty)
29 jsonw_pretty(_jw, true);
30 if (have_array)
31 jsonw_start_array(_jw);
32 }
33}
34
35static void __delete_json_obj(bool have_array)
36{
37 if (_jw) {
38 if (have_array)
39 jsonw_end_array(_jw);
40 jsonw_destroy(&_jw);
41 }
42}
43
44void new_json_obj(int json)
45{
46 __new_json_obj(json, true);
47}
48
49void delete_json_obj(void)
50{
51 __delete_json_obj(true);
52}
53
54void new_json_obj_plain(int json)
55{
56 __new_json_obj(json, false);
57}
58
59void delete_json_obj_plain(void)
60{
61 __delete_json_obj(false);
62}
63
64bool is_json_context(void)
65{
66 return _jw != NULL;
67}
68
69json_writer_t *get_json_writer(void)
70{
71 return _jw;
72}
73
74void open_json_object(const char *str)
75{
76 if (_IS_JSON_CONTEXT(PRINT_JSON)) {
77 if (str)
78 jsonw_name(_jw, str);
79 jsonw_start_object(_jw);
80 }
81}
82
83void close_json_object(void)
84{
85 if (_IS_JSON_CONTEXT(PRINT_JSON))
86 jsonw_end_object(_jw);
87}
88
89
90
91
92
93
94void open_json_array(enum output_type type, const char *str)
95{
96 if (_IS_JSON_CONTEXT(type)) {
97 if (str)
98 jsonw_name(_jw, str);
99 jsonw_start_array(_jw);
100 } else if (_IS_FP_CONTEXT(type)) {
101 printf("%s", str);
102 }
103}
104
105
106
107
108void close_json_array(enum output_type type, const char *str)
109{
110 if (_IS_JSON_CONTEXT(type)) {
111 jsonw_end_array(_jw);
112 } else if (_IS_FP_CONTEXT(type)) {
113 printf("%s", str);
114 }
115}
116
117
118
119
120
121#define _PRINT_FUNC(type_name, type) \
122 __attribute__((format(printf, 4, 0))) \
123 int print_color_##type_name(enum output_type t, \
124 enum color_attr color, \
125 const char *key, \
126 const char *fmt, \
127 type value) \
128 { \
129 int ret = 0; \
130 if (_IS_JSON_CONTEXT(t)) { \
131 if (!key) \
132 jsonw_##type_name(_jw, value); \
133 else \
134 jsonw_##type_name##_field(_jw, key, value); \
135 } else if (_IS_FP_CONTEXT(t)) { \
136 ret = color_fprintf(stdout, color, fmt, value); \
137 } \
138 return ret; \
139 }
140_PRINT_FUNC(int, int);
141_PRINT_FUNC(s64, int64_t);
142_PRINT_FUNC(hhu, unsigned char);
143_PRINT_FUNC(hu, unsigned short);
144_PRINT_FUNC(uint, unsigned int);
145_PRINT_FUNC(u64, uint64_t);
146_PRINT_FUNC(luint, unsigned long);
147_PRINT_FUNC(lluint, unsigned long long);
148_PRINT_FUNC(float, double);
149#undef _PRINT_FUNC
150
151#define _PRINT_NAME_VALUE_FUNC(type_name, type, format_char) \
152 void print_##type_name##_name_value(const char *name, type value)\
153 { \
154 SPRINT_BUF(format); \
155 \
156 snprintf(format, SPRINT_BSIZE, \
157 "%s %%"#format_char, name); \
158 print_##type_name(PRINT_ANY, name, format, value); \
159 }
160_PRINT_NAME_VALUE_FUNC(uint, unsigned int, u);
161_PRINT_NAME_VALUE_FUNC(string, const char*, s);
162#undef _PRINT_NAME_VALUE_FUNC
163
164int print_color_string(enum output_type type,
165 enum color_attr color,
166 const char *key,
167 const char *fmt,
168 const char *value)
169{
170 int ret = 0;
171
172 if (_IS_JSON_CONTEXT(type)) {
173 if (key && !value)
174 jsonw_name(_jw, key);
175 else if (!key && value)
176 jsonw_string(_jw, value);
177 else
178 jsonw_string_field(_jw, key, value);
179 } else if (_IS_FP_CONTEXT(type)) {
180 ret = color_fprintf(stdout, color, fmt, value);
181 }
182
183 return ret;
184}
185
186
187
188
189
190
191static int __print_color_bool(enum output_type type,
192 enum color_attr color,
193 const char *key,
194 const char *fmt,
195 bool value,
196 const char *str)
197{
198 int ret = 0;
199
200 if (_IS_JSON_CONTEXT(type)) {
201 if (key)
202 jsonw_bool_field(_jw, key, value);
203 else
204 jsonw_bool(_jw, value);
205 } else if (_IS_FP_CONTEXT(type)) {
206 ret = color_fprintf(stdout, color, fmt, str);
207 }
208
209 return ret;
210}
211
212int print_color_bool(enum output_type type,
213 enum color_attr color,
214 const char *key,
215 const char *fmt,
216 bool value)
217{
218 return __print_color_bool(type, color, key, fmt, value,
219 value ? "true" : "false");
220}
221
222int print_color_on_off(enum output_type type,
223 enum color_attr color,
224 const char *key,
225 const char *fmt,
226 bool value)
227{
228 return __print_color_bool(type, color, key, fmt, value,
229 value ? "on" : "off");
230}
231
232
233
234
235int print_color_0xhex(enum output_type type,
236 enum color_attr color,
237 const char *key,
238 const char *fmt,
239 unsigned long long hex)
240{
241 int ret = 0;
242
243 if (_IS_JSON_CONTEXT(type)) {
244 SPRINT_BUF(b1);
245
246 snprintf(b1, sizeof(b1), "%#llx", hex);
247 print_string(PRINT_JSON, key, NULL, b1);
248 } else if (_IS_FP_CONTEXT(type)) {
249 ret = color_fprintf(stdout, color, fmt, hex);
250 }
251
252 return ret;
253}
254
255int print_color_hex(enum output_type type,
256 enum color_attr color,
257 const char *key,
258 const char *fmt,
259 unsigned int hex)
260{
261 int ret = 0;
262
263 if (_IS_JSON_CONTEXT(type)) {
264 SPRINT_BUF(b1);
265
266 snprintf(b1, sizeof(b1), "%x", hex);
267 if (key)
268 jsonw_string_field(_jw, key, b1);
269 else
270 jsonw_string(_jw, b1);
271 } else if (_IS_FP_CONTEXT(type)) {
272 ret = color_fprintf(stdout, color, fmt, hex);
273 }
274
275 return ret;
276}
277
278
279
280
281
282int print_color_null(enum output_type type,
283 enum color_attr color,
284 const char *key,
285 const char *fmt,
286 const char *value)
287{
288 int ret = 0;
289
290 if (_IS_JSON_CONTEXT(type)) {
291 if (key)
292 jsonw_null_field(_jw, key);
293 else
294 jsonw_null(_jw);
295 } else if (_IS_FP_CONTEXT(type)) {
296 ret = color_fprintf(stdout, color, fmt, value);
297 }
298
299 return ret;
300}
301
302
303
304
305
306
307#pragma GCC diagnostic push
308#pragma GCC diagnostic ignored "-Wformat-nonliteral"
309int print_color_tv(enum output_type type,
310 enum color_attr color,
311 const char *key,
312 const char *fmt,
313 const struct timeval *tv)
314{
315 double usecs = tv->tv_usec;
316 double secs = tv->tv_sec;
317 double time = secs + usecs / 1000000;
318
319 return print_color_float(type, color, key, fmt, time);
320}
321#pragma GCC diagnostic pop
322
323
324void print_nl(void)
325{
326 if (!_jw)
327 printf("%s", _SL_);
328}
329
330int print_color_rate(bool use_iec, enum output_type type, enum color_attr color,
331 const char *key, const char *fmt, unsigned long long rate)
332{
333 unsigned long kilo = use_iec ? 1024 : 1000;
334 const char *str = use_iec ? "i" : "";
335 static char *units[5] = {"", "K", "M", "G", "T"};
336 char *buf;
337 int rc;
338 int i;
339
340 if (_IS_JSON_CONTEXT(type))
341 return print_color_lluint(type, color, key, "%llu", rate);
342
343 rate <<= 3;
344
345 for (i = 0; i < ARRAY_SIZE(units) - 1; i++) {
346 if (rate < kilo)
347 break;
348 if (((rate % kilo) != 0) && rate < 1000*kilo)
349 break;
350 rate /= kilo;
351 }
352
353 rc = asprintf(&buf, "%.0f%s%sbit", (double)rate, units[i],
354 i > 0 ? str : "");
355 if (rc < 0)
356 return -1;
357
358 rc = print_color_string(type, color, key, fmt, buf);
359 free(buf);
360 return rc;
361}
362