]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/jsonwrt.c
2 * JSON output formatting functions.
4 * No copyright is claimed. This code is in the public domain; do with
7 * Written by Karel Zak <kzak@redhat.com>
18 * Requirements enumerated via testing (V8, Firefox, IE11):
20 * var charsToEscape = [];
21 * for (var i = 0; i < 65535; i += 1) {
23 * JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
25 * charsToEscape.push(i);
29 static void fputs_quoted_case_json(const char *data
, FILE *out
, int dir
, size_t size
)
34 for (p
= data
; p
&& *p
&& (!size
|| p
< data
+ size
); p
++) {
36 const unsigned int c
= (unsigned int) *p
;
38 /* From http://www.json.org
40 * The double-quote and backslashes would break out a string or
41 * init an escape sequence if not escaped.
43 * Note that single-quotes and forward slashes, while they're
44 * in the JSON spec, don't break double-quoted strings.
46 if (c
== '"' || c
== '\\') {
52 /* All non-control characters OK; do the case swap as required. */
55 * Don't use locale sensitive ctype.h functions for regular
56 * ASCII chars, because for example with Turkish locale
57 * (aka LANG=tr_TR.UTF-8) toupper('I') returns 'I'.
60 fputc(dir
== 1 ? c_toupper(c
) :
61 dir
== -1 ? c_tolower(c
) : *p
, out
);
63 fputc(dir
== 1 ? toupper(c
) :
64 dir
== -1 ? tolower(c
) : *p
, out
);
68 /* In addition, all chars under ' ' break Node's/V8/Chrome's, and
69 * Firefox's JSON.parse function
72 /* Handle short-hand cases to reduce output size. C
73 * has most of the same stuff here, so if there's an
74 * "Escape for C" function somewhere in the STL, we
75 * should probably be using it.
93 /* Other assorted control characters */
94 fprintf(out
, "\\u00%02x", c
);
101 #define fputs_quoted_json(_d, _o) fputs_quoted_case_json(_d, _o, 0, 0)
102 #define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1, 0)
103 #define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1, 0)
105 void ul_jsonwrt_init(struct ul_jsonwrt
*fmt
, FILE *out
, int indent
)
108 fmt
->indent
= indent
;
109 fmt
->after_close
= 0;
112 int ul_jsonwrt_is_ready(struct ul_jsonwrt
*fmt
)
114 return fmt
->out
== NULL
? 0 : 1;
117 void ul_jsonwrt_indent(struct ul_jsonwrt
*fmt
)
121 for (i
= 0; i
< fmt
->indent
; i
++)
122 fputs(" ", fmt
->out
);
125 void ul_jsonwrt_open(struct ul_jsonwrt
*fmt
, const char *name
, int type
)
128 if (fmt
->after_close
)
129 fputs(",\n", fmt
->out
);
130 ul_jsonwrt_indent(fmt
);
131 fputs_quoted_json_lower(name
, fmt
->out
);
133 if (fmt
->after_close
)
134 fputs(",", fmt
->out
);
136 ul_jsonwrt_indent(fmt
);
141 fputs(name
? ": {\n" : "{\n", fmt
->out
);
145 fputs(name
? ": [\n" : "[\n", fmt
->out
);
149 fputs(name
? ": " : " ", fmt
->out
);
152 fmt
->after_close
= 0;
155 void ul_jsonwrt_close(struct ul_jsonwrt
*fmt
, int type
)
157 assert(fmt
->indent
> 0);
162 fputc('\n', fmt
->out
);
163 ul_jsonwrt_indent(fmt
);
164 fputs("}", fmt
->out
);
165 if (fmt
->indent
== 0)
166 fputs("\n", fmt
->out
);
170 fputc('\n', fmt
->out
);
171 ul_jsonwrt_indent(fmt
);
172 fputs("]", fmt
->out
);
178 fmt
->after_close
= 1;
181 void ul_jsonwrt_value_raw(struct ul_jsonwrt
*fmt
,
182 const char *name
, const char *data
)
184 ul_jsonwrt_value_open(fmt
, name
);
186 fputs(data
, fmt
->out
);
188 fputs("null", fmt
->out
);
189 ul_jsonwrt_value_close(fmt
);
192 void ul_jsonwrt_value_s(struct ul_jsonwrt
*fmt
,
193 const char *name
, const char *data
)
195 ul_jsonwrt_value_open(fmt
, name
);
197 fputs_quoted_json(data
, fmt
->out
);
199 fputs("null", fmt
->out
);
200 ul_jsonwrt_value_close(fmt
);
203 void ul_jsonwrt_value_s_sized(struct ul_jsonwrt
*fmt
,
204 const char *name
, const char *data
, size_t size
)
206 ul_jsonwrt_value_open(fmt
, name
);
208 fputs_quoted_case_json(data
, fmt
->out
, 0, size
);
210 fputs("null", fmt
->out
);
211 ul_jsonwrt_value_close(fmt
);
214 void ul_jsonwrt_value_u64(struct ul_jsonwrt
*fmt
,
215 const char *name
, uint64_t data
)
217 ul_jsonwrt_value_open(fmt
, name
);
218 fprintf(fmt
->out
, "%"PRIu64
, data
);
219 ul_jsonwrt_value_close(fmt
);
222 void ul_jsonwrt_value_double(struct ul_jsonwrt
*fmt
,
223 const char *name
, long double data
)
225 ul_jsonwrt_value_open(fmt
, name
);
226 fprintf(fmt
->out
, "%Lg", data
);
227 ul_jsonwrt_value_close(fmt
);
230 void ul_jsonwrt_value_boolean(struct ul_jsonwrt
*fmt
,
231 const char *name
, int data
)
233 ul_jsonwrt_value_open(fmt
, name
);
234 fputs(data
? "true" : "false", fmt
->out
);
235 ul_jsonwrt_value_close(fmt
);
238 void ul_jsonwrt_value_null(struct ul_jsonwrt
*fmt
,
241 ul_jsonwrt_value_open(fmt
, name
);
242 fputs("null", fmt
->out
);
243 ul_jsonwrt_value_close(fmt
);