]> git.proxmox.com Git - mirror_iproute2.git/blame - lib/json_print.c
ip: add support for seg6local End.BPF action
[mirror_iproute2.git] / lib / json_print.c
CommitLineData
6377572f 1/*
0b4b35e1 2 * json_print.c "print regular or json output, based on json_writer".
6377572f
JF
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>
6377572f
JF
10 */
11
12#include <stdarg.h>
13#include <stdio.h>
14
15#include "utils.h"
0b4b35e1 16#include "json_print.h"
6377572f
JF
17
18static json_writer_t *_jw;
6377572f
JF
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
429f314e 23void new_json_obj(int json)
6377572f
JF
24{
25 if (json) {
429f314e 26 _jw = jsonw_new(stdout);
6377572f
JF
27 if (!_jw) {
28 perror("json object");
29 exit(1);
30 }
54336567 31 if (pretty)
a233caa0 32 jsonw_pretty(_jw, true);
6377572f
JF
33 jsonw_start_array(_jw);
34 }
6377572f
JF
35}
36
37void delete_json_obj(void)
38{
39 if (_jw) {
40 jsonw_end_array(_jw);
41 jsonw_destroy(&_jw);
42 }
43}
44
45bool is_json_context(void)
46{
47 return _jw != NULL;
48}
49
6377572f
JF
50json_writer_t *get_json_writer(void)
51{
52 return _jw;
53}
54
55void 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
64void 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 */
75void 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)) {
429f314e 82 printf("%s", str);
6377572f
JF
83 }
84}
85
86/*
87 * End json array or string array
88 */
89void close_json_array(enum output_type type, const char *str)
90{
91 if (_IS_JSON_CONTEXT(type)) {
6377572f 92 jsonw_end_array(_jw);
6377572f 93 } else if (_IS_FP_CONTEXT(type)) {
429f314e 94 printf("%s", str);
6377572f
JF
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 void print_color_##type_name(enum output_type t, \
104 enum color_attr color, \
105 const char *key, \
106 const char *fmt, \
107 type value) \
108 { \
109 if (_IS_JSON_CONTEXT(t)) { \
110 if (!key) \
111 jsonw_##type_name(_jw, value); \
112 else \
113 jsonw_##type_name##_field(_jw, key, value); \
114 } else if (_IS_FP_CONTEXT(t)) { \
429f314e 115 color_fprintf(stdout, color, fmt, value); \
6377572f
JF
116 } \
117 }
118_PRINT_FUNC(int, int);
4db2ff0d 119_PRINT_FUNC(s64, int64_t);
6377572f 120_PRINT_FUNC(hu, unsigned short);
4db2ff0d
THJ
121_PRINT_FUNC(uint, unsigned int);
122_PRINT_FUNC(u64, uint64_t);
123_PRINT_FUNC(luint, unsigned long int);
6377572f 124_PRINT_FUNC(lluint, unsigned long long int);
097415d5 125_PRINT_FUNC(float, double);
6377572f
JF
126#undef _PRINT_FUNC
127
128void print_color_string(enum output_type type,
129 enum color_attr color,
130 const char *key,
131 const char *fmt,
132 const char *value)
133{
134 if (_IS_JSON_CONTEXT(type)) {
135 if (key && !value)
136 jsonw_name(_jw, key);
137 else if (!key && value)
138 jsonw_string(_jw, value);
139 else
140 jsonw_string_field(_jw, key, value);
141 } else if (_IS_FP_CONTEXT(type)) {
429f314e 142 color_fprintf(stdout, color, fmt, value);
6377572f
JF
143 }
144}
145
146/*
147 * value's type is bool. When using this function in FP context you can't pass
148 * a value to it, you will need to use "is_json_context()" to have different
149 * branch for json and regular output. grep -r "print_bool" for example
150 */
151void print_color_bool(enum output_type type,
152 enum color_attr color,
153 const char *key,
154 const char *fmt,
155 bool value)
156{
157 if (_IS_JSON_CONTEXT(type)) {
158 if (key)
159 jsonw_bool_field(_jw, key, value);
160 else
161 jsonw_bool(_jw, value);
162 } else if (_IS_FP_CONTEXT(type)) {
429f314e 163 color_fprintf(stdout, color, fmt, value ? "true" : "false");
6377572f
JF
164 }
165}
166
167/*
168 * In JSON context uses hardcode %#x format: 42 -> 0x2a
169 */
170void print_color_0xhex(enum output_type type,
171 enum color_attr color,
172 const char *key,
173 const char *fmt,
174 unsigned int hex)
175{
176 if (_IS_JSON_CONTEXT(type)) {
177 SPRINT_BUF(b1);
178
179 snprintf(b1, sizeof(b1), "%#x", hex);
180 print_string(PRINT_JSON, key, NULL, b1);
181 } else if (_IS_FP_CONTEXT(type)) {
429f314e 182 color_fprintf(stdout, color, fmt, hex);
6377572f
JF
183 }
184}
185
186void print_color_hex(enum output_type type,
187 enum color_attr color,
188 const char *key,
189 const char *fmt,
190 unsigned int hex)
191{
192 if (_IS_JSON_CONTEXT(type)) {
193 SPRINT_BUF(b1);
194
195 snprintf(b1, sizeof(b1), "%x", hex);
196 if (key)
197 jsonw_string_field(_jw, key, b1);
198 else
199 jsonw_string(_jw, b1);
200 } else if (_IS_FP_CONTEXT(type)) {
429f314e 201 color_fprintf(stdout, color, fmt, hex);
6377572f
JF
202 }
203}
204
205/*
206 * In JSON context we don't use the argument "value" we simply call jsonw_null
207 * whereas FP context can use "value" to output anything
208 */
209void print_color_null(enum output_type type,
210 enum color_attr color,
211 const char *key,
212 const char *fmt,
213 const char *value)
214{
215 if (_IS_JSON_CONTEXT(type)) {
216 if (key)
217 jsonw_null_field(_jw, key);
218 else
219 jsonw_null(_jw);
220 } else if (_IS_FP_CONTEXT(type)) {
429f314e 221 color_fprintf(stdout, color, fmt, value);
6377572f
JF
222 }
223}