xref: /spdk/lib/json/json_write.c (revision 04c48172b9879a8824de83c842087d871c433d12)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "json_internal.h"
35 
36 struct spdk_json_write_ctx {
37 	spdk_json_write_cb write_cb;
38 	void *cb_ctx;
39 	uint32_t flags;
40 	uint32_t indent;
41 	bool new_indent;
42 	bool first_value;
43 	bool failed;
44 };
45 
46 struct spdk_json_write_ctx *
47 spdk_json_write_begin(spdk_json_write_cb write_cb, void *cb_ctx, uint32_t flags)
48 {
49 	struct spdk_json_write_ctx *w;
50 
51 	w = calloc(1, sizeof(*w));
52 	if (w == NULL) {
53 		return w;
54 	}
55 
56 	w->write_cb = write_cb;
57 	w->cb_ctx = cb_ctx;
58 	w->flags = flags;
59 	w->indent = 0;
60 	w->new_indent = false;
61 	w->first_value = true;
62 	w->failed = false;
63 
64 	return w;
65 }
66 
67 int
68 spdk_json_write_end(struct spdk_json_write_ctx *w)
69 {
70 	bool failed;
71 
72 	if (w == NULL) {
73 		return 0;
74 	}
75 
76 	failed = w->failed;
77 
78 	free(w);
79 
80 	return failed ? -1 : 0;
81 }
82 
83 static int
84 fail(struct spdk_json_write_ctx *w)
85 {
86 	w->failed = true;
87 	return -1;
88 }
89 
90 static int
91 emit(struct spdk_json_write_ctx *w, const void *data, size_t size)
92 {
93 	int rc;
94 
95 	rc = w->write_cb(w->cb_ctx, data, size);
96 	if (rc != 0) {
97 		return fail(w);
98 	}
99 	return 0;
100 }
101 
102 static int
103 emit_fmt(struct spdk_json_write_ctx *w, const void *data, size_t size)
104 {
105 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
106 		return emit(w, data, size);
107 	}
108 	return 0;
109 }
110 
111 static int
112 emit_indent(struct spdk_json_write_ctx *w)
113 {
114 	uint32_t i;
115 
116 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
117 		for (i = 0; i < w->indent; i++) {
118 			if (emit(w, "  ", 2)) return fail(w);
119 		}
120 	}
121 	return 0;
122 }
123 
124 static int
125 begin_value(struct spdk_json_write_ctx *w)
126 {
127 	// TODO: check for value state
128 	if (w->new_indent) {
129 		if (emit_fmt(w, "\n", 1)) return fail(w);
130 		if (emit_indent(w)) return fail(w);
131 	}
132 	if (!w->first_value) {
133 		if (emit(w, ",", 1)) return fail(w);
134 		if (emit_fmt(w, "\n", 1)) return fail(w);
135 		if (emit_indent(w)) return fail(w);
136 	}
137 	w->first_value = false;
138 	w->new_indent = false;
139 	return 0;
140 }
141 
142 int
143 spdk_json_write_val_raw(struct spdk_json_write_ctx *w, const void *data, size_t len)
144 {
145 	if (begin_value(w)) return fail(w);
146 	return emit(w, data, len);
147 }
148 
149 int
150 spdk_json_write_null(struct spdk_json_write_ctx *w)
151 {
152 	if (begin_value(w)) return fail(w);
153 	return emit(w, "null", 4);
154 }
155 
156 int
157 spdk_json_write_bool(struct spdk_json_write_ctx *w, bool val)
158 {
159 	if (begin_value(w)) return fail(w);
160 	if (val) {
161 		return emit(w, "true", 4);
162 	} else {
163 		return emit(w, "false", 5);
164 	}
165 }
166 
167 int
168 spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val)
169 {
170 	char buf[32];
171 	int count;
172 
173 	if (begin_value(w)) return fail(w);
174 	count = snprintf(buf, sizeof(buf), "%" PRId32, val);
175 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
176 	return emit(w, buf, count);
177 }
178 
179 int
180 spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val)
181 {
182 	char buf[32];
183 	int count;
184 
185 	if (begin_value(w)) return fail(w);
186 	count = snprintf(buf, sizeof(buf), "%" PRIu32, val);
187 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
188 	return emit(w, buf, count);
189 }
190 
191 int
192 spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val)
193 {
194 	char buf[32];
195 	int count;
196 
197 	if (begin_value(w)) return fail(w);
198 	count = snprintf(buf, sizeof(buf), "%" PRId64, val);
199 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
200 	return emit(w, buf, count);
201 }
202 
203 int
204 spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val)
205 {
206 	char buf[32];
207 	int count;
208 
209 	if (begin_value(w)) return fail(w);
210 	count = snprintf(buf, sizeof(buf), "%" PRIu64, val);
211 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
212 	return emit(w, buf, count);
213 }
214 
215 static void
216 write_hex_4(void *dest, uint16_t val)
217 {
218 	uint8_t *p = dest;
219 	char hex[] = "0123456789ABCDEF";
220 
221 	p[0] = hex[(val >> 12)];
222 	p[1] = hex[(val >> 8) & 0xF];
223 	p[2] = hex[(val >> 4) & 0xF];
224 	p[3] = hex[val & 0xF];
225 }
226 
227 static int
228 write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
229 {
230 	const uint8_t *p = val;
231 	const uint8_t *end = val + len;
232 	static const uint8_t escapes[] = {
233 		['\b'] = 'b',
234 		['\f'] = 'f',
235 		['\n'] = 'n',
236 		['\r'] = 'r',
237 		['\t'] = 't',
238 		['"'] = '"',
239 		['\\'] = '\\',
240 		/*
241 		 * Forward slash (/) is intentionally not converted to an escape
242 		 *  (it is valid unescaped).
243 		 */
244 	};
245 
246 	if (emit(w, "\"", 1)) return fail(w);
247 
248 	while (p != end) {
249 		int codepoint_len;
250 		uint32_t codepoint;
251 		uint16_t high, low;
252 		char out[13];
253 		size_t out_len;
254 
255 		codepoint_len = utf8_valid(p, end);
256 		switch (codepoint_len) {
257 		case 1:
258 			codepoint = utf8_decode_unsafe_1(p);
259 			break;
260 		case 2:
261 			codepoint = utf8_decode_unsafe_2(p);
262 			break;
263 		case 3:
264 			codepoint = utf8_decode_unsafe_3(p);
265 			break;
266 		case 4:
267 			codepoint = utf8_decode_unsafe_4(p);
268 			break;
269 		default:
270 			return fail(w);
271 		}
272 
273 		if (codepoint < sizeof(escapes) && escapes[codepoint]) {
274 			out[0] = '\\';
275 			out[1] = escapes[codepoint];
276 			out_len = 2;
277 		} else if (codepoint >= 0x20 && codepoint < 0x7F) {
278 			/*
279 			 * Encode plain ASCII directly (except 0x7F, since it is really
280 			 *  a control character, despite the JSON spec not considering it one).
281 			 */
282 			out[0] = (uint8_t)codepoint;
283 			out_len = 1;
284 		} else if (codepoint < 0x10000) {
285 			out[0] = '\\';
286 			out[1] = 'u';
287 			write_hex_4(&out[2], (uint16_t)codepoint);
288 			out_len = 6;
289 		} else {
290 			utf16_encode_surrogate_pair(codepoint, &high, &low);
291 			out[0] = '\\';
292 			out[1] = 'u';
293 			write_hex_4(&out[2], high);
294 			out[6] = '\\';
295 			out[7] = 'u';
296 			write_hex_4(&out[8], low);
297 			out_len = 12;
298 		}
299 
300 		if (emit(w, out, out_len)) return fail(w);
301 		p += codepoint_len;
302 	}
303 
304 	return emit(w, "\"", 1);
305 }
306 
307 int
308 spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len)
309 {
310 	if (begin_value(w)) return fail(w);
311 	return write_string_or_name(w, val, len);
312 }
313 
314 int
315 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
316 {
317 	return spdk_json_write_string_raw(w, val, strlen(val));
318 }
319 
320 int
321 spdk_json_write_array_begin(struct spdk_json_write_ctx *w)
322 {
323 	if (begin_value(w)) return fail(w);
324 	w->first_value = true;
325 	w->new_indent = true;
326 	w->indent++;
327 	if (emit(w, "[", 1)) return fail(w);
328 	return 0;
329 }
330 
331 int
332 spdk_json_write_array_end(struct spdk_json_write_ctx *w)
333 {
334 	w->first_value = false;
335 	if (w->indent == 0) return fail(w);
336 	w->indent--;
337 	if (!w->new_indent) {
338 		if (emit_fmt(w, "\n", 1)) return fail(w);
339 		if (emit_indent(w)) return fail(w);
340 	}
341 	w->new_indent = false;
342 	return emit(w, "]", 1);
343 }
344 
345 int
346 spdk_json_write_object_begin(struct spdk_json_write_ctx *w)
347 {
348 	if (begin_value(w)) return fail(w);
349 	w->first_value = true;
350 	w->new_indent = true;
351 	w->indent++;
352 	if (emit(w, "{", 1)) return fail(w);
353 	return 0;
354 }
355 
356 int
357 spdk_json_write_object_end(struct spdk_json_write_ctx *w)
358 {
359 	w->first_value = false;
360 	w->indent--;
361 	if (!w->new_indent) {
362 		if (emit_fmt(w, "\n", 1)) return fail(w);
363 		if (emit_indent(w)) return fail(w);
364 	}
365 	w->new_indent = false;
366 	return emit(w, "}", 1);
367 }
368 
369 int
370 spdk_json_write_name_raw(struct spdk_json_write_ctx *w, const char *name, size_t len)
371 {
372 	/* TODO: check that container is an object */
373 	if (begin_value(w)) return fail(w);
374 	if (write_string_or_name(w, name, len)) return fail(w);
375 	w->first_value = true;
376 	if (emit(w, ":", 1)) return fail(w);
377 	return emit_fmt(w, " ", 1);
378 }
379 
380 int
381 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
382 {
383 	return spdk_json_write_name_raw(w, name, strlen(name));
384 }
385 
386 int
387 spdk_json_write_val(struct spdk_json_write_ctx *w, const struct spdk_json_val *val)
388 {
389 	size_t num_values, i;
390 
391 	switch (val->type) {
392 	case SPDK_JSON_VAL_NUMBER:
393 		return spdk_json_write_val_raw(w, val->start, val->len);
394 
395 	case SPDK_JSON_VAL_STRING:
396 		return spdk_json_write_string_raw(w, val->start, val->len);
397 
398 	case SPDK_JSON_VAL_NAME:
399 		return spdk_json_write_name_raw(w, val->start, val->len);
400 
401 	case SPDK_JSON_VAL_TRUE:
402 		return spdk_json_write_bool(w, true);
403 
404 	case SPDK_JSON_VAL_FALSE:
405 		return spdk_json_write_bool(w, false);
406 
407 	case SPDK_JSON_VAL_NULL:
408 		return spdk_json_write_null(w);
409 
410 	case SPDK_JSON_VAL_ARRAY_BEGIN:
411 	case SPDK_JSON_VAL_OBJECT_BEGIN:
412 		num_values = val[0].len;
413 
414 		if (val[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
415 			if (spdk_json_write_object_begin(w)) {
416 				return fail(w);
417 			}
418 		} else {
419 			if (spdk_json_write_array_begin(w)) {
420 				return fail(w);
421 			}
422 		}
423 
424 		// Loop up to and including the _END value
425 		for (i = 0; i < num_values + 1;) {
426 			if (spdk_json_write_val(w, &val[i + 1])) {
427 				return fail(w);
428 			}
429 			if (val[i + 1].type == SPDK_JSON_VAL_ARRAY_BEGIN ||
430 			    val[i + 1].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
431 				i += val[i + 1].len + 2;
432 			} else {
433 				i++;
434 			}
435 		}
436 		return 0;
437 
438 	case SPDK_JSON_VAL_ARRAY_END:
439 		return spdk_json_write_array_end(w);
440 
441 	case SPDK_JSON_VAL_OBJECT_END:
442 		return spdk_json_write_object_end(w);
443 
444 	case SPDK_JSON_VAL_INVALID:
445 		// Handle INVALID to make the compiler happy (and catch other unhandled types)
446 		return fail(w);
447 	}
448 
449 	return fail(w);
450 }
451