xref: /spdk/lib/json/json_write.c (revision edbca2a67610cf6ebb9755c839e307d1d18375da)
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 	size_t buf_filled;
45 	uint8_t buf[4096];
46 };
47 
48 static int emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size);
49 
50 static int
51 fail(struct spdk_json_write_ctx *w)
52 {
53 	w->failed = true;
54 	return -1;
55 }
56 
57 static int
58 flush_buf(struct spdk_json_write_ctx *w)
59 {
60 	int rc;
61 
62 	rc = w->write_cb(w->cb_ctx, w->buf, w->buf_filled);
63 	if (rc != 0) {
64 		return fail(w);
65 	}
66 
67 	w->buf_filled = 0;
68 
69 	return 0;
70 }
71 
72 struct spdk_json_write_ctx *
73 spdk_json_write_begin(spdk_json_write_cb write_cb, void *cb_ctx, uint32_t flags)
74 {
75 	struct spdk_json_write_ctx *w;
76 
77 	w = calloc(1, sizeof(*w));
78 	if (w == NULL) {
79 		return w;
80 	}
81 
82 	w->write_cb = write_cb;
83 	w->cb_ctx = cb_ctx;
84 	w->flags = flags;
85 	w->indent = 0;
86 	w->new_indent = false;
87 	w->first_value = true;
88 	w->failed = false;
89 	w->buf_filled = 0;
90 
91 	return w;
92 }
93 
94 int
95 spdk_json_write_end(struct spdk_json_write_ctx *w)
96 {
97 	bool failed;
98 	int rc;
99 
100 	if (w == NULL) {
101 		return 0;
102 	}
103 
104 	failed = w->failed;
105 
106 	rc = flush_buf(w);
107 	if (rc != 0) {
108 		failed = true;
109 	}
110 
111 	free(w);
112 
113 	return failed ? -1 : 0;
114 }
115 
116 static inline int
117 emit(struct spdk_json_write_ctx *w, const void *data, size_t size)
118 {
119 	size_t buf_remain = sizeof(w->buf) - w->buf_filled;
120 
121 	if (spdk_unlikely(size > buf_remain)) {
122 		/* Not enough space in buffer for the new data. */
123 		return emit_buf_full(w, data, size);
124 	}
125 
126 	/* Copy the new data into buf. */
127 	memcpy(w->buf + w->buf_filled, data, size);
128 	w->buf_filled += size;
129 	return 0;
130 }
131 
132 static int
133 emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size)
134 {
135 	size_t buf_remain = sizeof(w->buf) - w->buf_filled;
136 	int rc;
137 
138 	assert(size > buf_remain);
139 
140 	/* Copy as much of the new data as possible into the buffer and flush it. */
141 	memcpy(w->buf + w->buf_filled, data, buf_remain);
142 	w->buf_filled += buf_remain;
143 
144 	rc = flush_buf(w);
145 	if (rc != 0) {
146 		return fail(w);
147 	}
148 
149 	/* Recurse to emit the rest of the data. */
150 	return emit(w, data + buf_remain, size - buf_remain);
151 }
152 
153 static int
154 emit_fmt(struct spdk_json_write_ctx *w, const void *data, size_t size)
155 {
156 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
157 		return emit(w, data, size);
158 	}
159 	return 0;
160 }
161 
162 static int
163 emit_indent(struct spdk_json_write_ctx *w)
164 {
165 	uint32_t i;
166 
167 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
168 		for (i = 0; i < w->indent; i++) {
169 			if (emit(w, "  ", 2)) return fail(w);
170 		}
171 	}
172 	return 0;
173 }
174 
175 static int
176 begin_value(struct spdk_json_write_ctx *w)
177 {
178 	// TODO: check for value state
179 	if (w->new_indent) {
180 		if (emit_fmt(w, "\n", 1)) return fail(w);
181 		if (emit_indent(w)) return fail(w);
182 	}
183 	if (!w->first_value) {
184 		if (emit(w, ",", 1)) return fail(w);
185 		if (emit_fmt(w, "\n", 1)) return fail(w);
186 		if (emit_indent(w)) return fail(w);
187 	}
188 	w->first_value = false;
189 	w->new_indent = false;
190 	return 0;
191 }
192 
193 int
194 spdk_json_write_val_raw(struct spdk_json_write_ctx *w, const void *data, size_t len)
195 {
196 	if (begin_value(w)) return fail(w);
197 	return emit(w, data, len);
198 }
199 
200 int
201 spdk_json_write_null(struct spdk_json_write_ctx *w)
202 {
203 	if (begin_value(w)) return fail(w);
204 	return emit(w, "null", 4);
205 }
206 
207 int
208 spdk_json_write_bool(struct spdk_json_write_ctx *w, bool val)
209 {
210 	if (begin_value(w)) return fail(w);
211 	if (val) {
212 		return emit(w, "true", 4);
213 	} else {
214 		return emit(w, "false", 5);
215 	}
216 }
217 
218 int
219 spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val)
220 {
221 	char buf[32];
222 	int count;
223 
224 	if (begin_value(w)) return fail(w);
225 	count = snprintf(buf, sizeof(buf), "%" PRId32, val);
226 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
227 	return emit(w, buf, count);
228 }
229 
230 int
231 spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val)
232 {
233 	char buf[32];
234 	int count;
235 
236 	if (begin_value(w)) return fail(w);
237 	count = snprintf(buf, sizeof(buf), "%" PRIu32, val);
238 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
239 	return emit(w, buf, count);
240 }
241 
242 int
243 spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val)
244 {
245 	char buf[32];
246 	int count;
247 
248 	if (begin_value(w)) return fail(w);
249 	count = snprintf(buf, sizeof(buf), "%" PRId64, val);
250 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
251 	return emit(w, buf, count);
252 }
253 
254 int
255 spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val)
256 {
257 	char buf[32];
258 	int count;
259 
260 	if (begin_value(w)) return fail(w);
261 	count = snprintf(buf, sizeof(buf), "%" PRIu64, val);
262 	if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w);
263 	return emit(w, buf, count);
264 }
265 
266 static void
267 write_hex_4(void *dest, uint16_t val)
268 {
269 	uint8_t *p = dest;
270 	char hex[] = "0123456789ABCDEF";
271 
272 	p[0] = hex[(val >> 12)];
273 	p[1] = hex[(val >> 8) & 0xF];
274 	p[2] = hex[(val >> 4) & 0xF];
275 	p[3] = hex[val & 0xF];
276 }
277 
278 static int
279 write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
280 {
281 	const uint8_t *p = val;
282 	const uint8_t *end = val + len;
283 	static const uint8_t escapes[] = {
284 		['\b'] = 'b',
285 		['\f'] = 'f',
286 		['\n'] = 'n',
287 		['\r'] = 'r',
288 		['\t'] = 't',
289 		['"'] = '"',
290 		['\\'] = '\\',
291 		/*
292 		 * Forward slash (/) is intentionally not converted to an escape
293 		 *  (it is valid unescaped).
294 		 */
295 	};
296 
297 	if (emit(w, "\"", 1)) return fail(w);
298 
299 	while (p != end) {
300 		int codepoint_len;
301 		uint32_t codepoint;
302 		uint16_t high, low;
303 		char out[13];
304 		size_t out_len;
305 
306 		codepoint_len = utf8_valid(p, end);
307 		switch (codepoint_len) {
308 		case 1:
309 			codepoint = utf8_decode_unsafe_1(p);
310 			break;
311 		case 2:
312 			codepoint = utf8_decode_unsafe_2(p);
313 			break;
314 		case 3:
315 			codepoint = utf8_decode_unsafe_3(p);
316 			break;
317 		case 4:
318 			codepoint = utf8_decode_unsafe_4(p);
319 			break;
320 		default:
321 			return fail(w);
322 		}
323 
324 		if (codepoint < sizeof(escapes) && escapes[codepoint]) {
325 			out[0] = '\\';
326 			out[1] = escapes[codepoint];
327 			out_len = 2;
328 		} else if (codepoint >= 0x20 && codepoint < 0x7F) {
329 			/*
330 			 * Encode plain ASCII directly (except 0x7F, since it is really
331 			 *  a control character, despite the JSON spec not considering it one).
332 			 */
333 			out[0] = (uint8_t)codepoint;
334 			out_len = 1;
335 		} else if (codepoint < 0x10000) {
336 			out[0] = '\\';
337 			out[1] = 'u';
338 			write_hex_4(&out[2], (uint16_t)codepoint);
339 			out_len = 6;
340 		} else {
341 			utf16_encode_surrogate_pair(codepoint, &high, &low);
342 			out[0] = '\\';
343 			out[1] = 'u';
344 			write_hex_4(&out[2], high);
345 			out[6] = '\\';
346 			out[7] = 'u';
347 			write_hex_4(&out[8], low);
348 			out_len = 12;
349 		}
350 
351 		if (emit(w, out, out_len)) return fail(w);
352 		p += codepoint_len;
353 	}
354 
355 	return emit(w, "\"", 1);
356 }
357 
358 int
359 spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len)
360 {
361 	if (begin_value(w)) return fail(w);
362 	return write_string_or_name(w, val, len);
363 }
364 
365 int
366 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
367 {
368 	return spdk_json_write_string_raw(w, val, strlen(val));
369 }
370 
371 int
372 spdk_json_write_string_fmt(struct spdk_json_write_ctx *w, const char *fmt, ...)
373 {
374 	char *s;
375 	va_list args;
376 	int rc;
377 
378 	va_start(args, fmt);
379 	s = spdk_vsprintf_alloc(fmt, args);
380 	va_end(args);
381 
382 	if (s == NULL) {
383 		return -1;
384 	}
385 
386 	rc = spdk_json_write_string(w, s);
387 	free(s);
388 	return rc;
389 }
390 
391 int
392 spdk_json_write_array_begin(struct spdk_json_write_ctx *w)
393 {
394 	if (begin_value(w)) return fail(w);
395 	w->first_value = true;
396 	w->new_indent = true;
397 	w->indent++;
398 	if (emit(w, "[", 1)) return fail(w);
399 	return 0;
400 }
401 
402 int
403 spdk_json_write_array_end(struct spdk_json_write_ctx *w)
404 {
405 	w->first_value = false;
406 	if (w->indent == 0) return fail(w);
407 	w->indent--;
408 	if (!w->new_indent) {
409 		if (emit_fmt(w, "\n", 1)) return fail(w);
410 		if (emit_indent(w)) return fail(w);
411 	}
412 	w->new_indent = false;
413 	return emit(w, "]", 1);
414 }
415 
416 int
417 spdk_json_write_object_begin(struct spdk_json_write_ctx *w)
418 {
419 	if (begin_value(w)) return fail(w);
420 	w->first_value = true;
421 	w->new_indent = true;
422 	w->indent++;
423 	if (emit(w, "{", 1)) return fail(w);
424 	return 0;
425 }
426 
427 int
428 spdk_json_write_object_end(struct spdk_json_write_ctx *w)
429 {
430 	w->first_value = false;
431 	w->indent--;
432 	if (!w->new_indent) {
433 		if (emit_fmt(w, "\n", 1)) return fail(w);
434 		if (emit_indent(w)) return fail(w);
435 	}
436 	w->new_indent = false;
437 	return emit(w, "}", 1);
438 }
439 
440 int
441 spdk_json_write_name_raw(struct spdk_json_write_ctx *w, const char *name, size_t len)
442 {
443 	/* TODO: check that container is an object */
444 	if (begin_value(w)) return fail(w);
445 	if (write_string_or_name(w, name, len)) return fail(w);
446 	w->first_value = true;
447 	if (emit(w, ":", 1)) return fail(w);
448 	return emit_fmt(w, " ", 1);
449 }
450 
451 int
452 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
453 {
454 	return spdk_json_write_name_raw(w, name, strlen(name));
455 }
456 
457 int
458 spdk_json_write_val(struct spdk_json_write_ctx *w, const struct spdk_json_val *val)
459 {
460 	size_t num_values, i;
461 
462 	switch (val->type) {
463 	case SPDK_JSON_VAL_NUMBER:
464 		return spdk_json_write_val_raw(w, val->start, val->len);
465 
466 	case SPDK_JSON_VAL_STRING:
467 		return spdk_json_write_string_raw(w, val->start, val->len);
468 
469 	case SPDK_JSON_VAL_NAME:
470 		return spdk_json_write_name_raw(w, val->start, val->len);
471 
472 	case SPDK_JSON_VAL_TRUE:
473 		return spdk_json_write_bool(w, true);
474 
475 	case SPDK_JSON_VAL_FALSE:
476 		return spdk_json_write_bool(w, false);
477 
478 	case SPDK_JSON_VAL_NULL:
479 		return spdk_json_write_null(w);
480 
481 	case SPDK_JSON_VAL_ARRAY_BEGIN:
482 	case SPDK_JSON_VAL_OBJECT_BEGIN:
483 		num_values = val[0].len;
484 
485 		if (val[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
486 			if (spdk_json_write_object_begin(w)) {
487 				return fail(w);
488 			}
489 		} else {
490 			if (spdk_json_write_array_begin(w)) {
491 				return fail(w);
492 			}
493 		}
494 
495 		// Loop up to and including the _END value
496 		for (i = 0; i < num_values + 1;) {
497 			if (spdk_json_write_val(w, &val[i + 1])) {
498 				return fail(w);
499 			}
500 			if (val[i + 1].type == SPDK_JSON_VAL_ARRAY_BEGIN ||
501 			    val[i + 1].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
502 				i += val[i + 1].len + 2;
503 			} else {
504 				i++;
505 			}
506 		}
507 		return 0;
508 
509 	case SPDK_JSON_VAL_ARRAY_END:
510 		return spdk_json_write_array_end(w);
511 
512 	case SPDK_JSON_VAL_OBJECT_END:
513 		return spdk_json_write_object_end(w);
514 
515 	case SPDK_JSON_VAL_INVALID:
516 		// Handle INVALID to make the compiler happy (and catch other unhandled types)
517 		return fail(w);
518 	}
519 
520 	return fail(w);
521 }
522