xref: /spdk/lib/json/json_write.c (revision 7506a7aa53d239f533af3bc768f0d2af55e735fe)
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 "spdk/json.h"
35 
36 #include "spdk_internal/utf.h"
37 
38 struct spdk_json_write_ctx {
39 	spdk_json_write_cb write_cb;
40 	void *cb_ctx;
41 	uint32_t flags;
42 	uint32_t indent;
43 	bool new_indent;
44 	bool first_value;
45 	bool failed;
46 	size_t buf_filled;
47 	uint8_t buf[4096];
48 };
49 
50 static int emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size);
51 
52 static int
53 fail(struct spdk_json_write_ctx *w)
54 {
55 	w->failed = true;
56 	return -1;
57 }
58 
59 static int
60 flush_buf(struct spdk_json_write_ctx *w)
61 {
62 	int rc;
63 
64 	rc = w->write_cb(w->cb_ctx, w->buf, w->buf_filled);
65 	if (rc != 0) {
66 		return fail(w);
67 	}
68 
69 	w->buf_filled = 0;
70 
71 	return 0;
72 }
73 
74 struct spdk_json_write_ctx *
75 spdk_json_write_begin(spdk_json_write_cb write_cb, void *cb_ctx, uint32_t flags)
76 {
77 	struct spdk_json_write_ctx *w;
78 
79 	w = calloc(1, sizeof(*w));
80 	if (w == NULL) {
81 		return w;
82 	}
83 
84 	w->write_cb = write_cb;
85 	w->cb_ctx = cb_ctx;
86 	w->flags = flags;
87 	w->indent = 0;
88 	w->new_indent = false;
89 	w->first_value = true;
90 	w->failed = false;
91 	w->buf_filled = 0;
92 
93 	return w;
94 }
95 
96 int
97 spdk_json_write_end(struct spdk_json_write_ctx *w)
98 {
99 	bool failed;
100 	int rc;
101 
102 	if (w == NULL) {
103 		return 0;
104 	}
105 
106 	failed = w->failed;
107 
108 	rc = flush_buf(w);
109 	if (rc != 0) {
110 		failed = true;
111 	}
112 
113 	free(w);
114 
115 	return failed ? -1 : 0;
116 }
117 
118 static inline int
119 emit(struct spdk_json_write_ctx *w, const void *data, size_t size)
120 {
121 	size_t buf_remain = sizeof(w->buf) - w->buf_filled;
122 
123 	if (spdk_unlikely(size > buf_remain)) {
124 		/* Not enough space in buffer for the new data. */
125 		return emit_buf_full(w, data, size);
126 	}
127 
128 	/* Copy the new data into buf. */
129 	memcpy(w->buf + w->buf_filled, data, size);
130 	w->buf_filled += size;
131 	return 0;
132 }
133 
134 static int
135 emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size)
136 {
137 	size_t buf_remain = sizeof(w->buf) - w->buf_filled;
138 	int rc;
139 
140 	assert(size > buf_remain);
141 
142 	/* Copy as much of the new data as possible into the buffer and flush it. */
143 	memcpy(w->buf + w->buf_filled, data, buf_remain);
144 	w->buf_filled += buf_remain;
145 
146 	rc = flush_buf(w);
147 	if (rc != 0) {
148 		return fail(w);
149 	}
150 
151 	/* Recurse to emit the rest of the data. */
152 	return emit(w, data + buf_remain, size - buf_remain);
153 }
154 
155 static int
156 emit_fmt(struct spdk_json_write_ctx *w, const void *data, size_t size)
157 {
158 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
159 		return emit(w, data, size);
160 	}
161 	return 0;
162 }
163 
164 static int
165 emit_indent(struct spdk_json_write_ctx *w)
166 {
167 	uint32_t i;
168 
169 	if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
170 		for (i = 0; i < w->indent; i++) {
171 			if (emit(w, "  ", 2)) { return fail(w); }
172 		}
173 	}
174 	return 0;
175 }
176 
177 static int
178 begin_value(struct spdk_json_write_ctx *w)
179 {
180 	/* TODO: check for value state */
181 	if (w->new_indent) {
182 		if (emit_fmt(w, "\n", 1)) { return fail(w); }
183 		if (emit_indent(w)) { return fail(w); }
184 	}
185 	if (!w->first_value) {
186 		if (emit(w, ",", 1)) { return fail(w); }
187 		if (emit_fmt(w, "\n", 1)) { return fail(w); }
188 		if (emit_indent(w)) { return fail(w); }
189 	}
190 	w->first_value = false;
191 	w->new_indent = false;
192 	return 0;
193 }
194 
195 int
196 spdk_json_write_val_raw(struct spdk_json_write_ctx *w, const void *data, size_t len)
197 {
198 	if (begin_value(w)) { return fail(w); }
199 	return emit(w, data, len);
200 }
201 
202 int
203 spdk_json_write_null(struct spdk_json_write_ctx *w)
204 {
205 	if (begin_value(w)) { return fail(w); }
206 	return emit(w, "null", 4);
207 }
208 
209 int
210 spdk_json_write_bool(struct spdk_json_write_ctx *w, bool val)
211 {
212 	if (begin_value(w)) { return fail(w); }
213 	if (val) {
214 		return emit(w, "true", 4);
215 	} else {
216 		return emit(w, "false", 5);
217 	}
218 }
219 
220 int
221 spdk_json_write_uint8(struct spdk_json_write_ctx *w, uint8_t val)
222 {
223 	char buf[32];
224 	int count;
225 
226 	if (begin_value(w)) { return fail(w); }
227 	count = snprintf(buf, sizeof(buf), "%" PRIu8, val);
228 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
229 	return emit(w, buf, count);
230 }
231 
232 int
233 spdk_json_write_uint16(struct spdk_json_write_ctx *w, uint16_t val)
234 {
235 	char buf[32];
236 	int count;
237 
238 	if (begin_value(w)) { return fail(w); }
239 	count = snprintf(buf, sizeof(buf), "%" PRIu16, val);
240 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
241 	return emit(w, buf, count);
242 }
243 
244 int
245 spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val)
246 {
247 	char buf[32];
248 	int count;
249 
250 	if (begin_value(w)) { return fail(w); }
251 	count = snprintf(buf, sizeof(buf), "%" PRId32, val);
252 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
253 	return emit(w, buf, count);
254 }
255 
256 int
257 spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val)
258 {
259 	char buf[32];
260 	int count;
261 
262 	if (begin_value(w)) { return fail(w); }
263 	count = snprintf(buf, sizeof(buf), "%" PRIu32, val);
264 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
265 	return emit(w, buf, count);
266 }
267 
268 int
269 spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val)
270 {
271 	char buf[32];
272 	int count;
273 
274 	if (begin_value(w)) { return fail(w); }
275 	count = snprintf(buf, sizeof(buf), "%" PRId64, val);
276 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
277 	return emit(w, buf, count);
278 }
279 
280 int
281 spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val)
282 {
283 	char buf[32];
284 	int count;
285 
286 	if (begin_value(w)) { return fail(w); }
287 	count = snprintf(buf, sizeof(buf), "%" PRIu64, val);
288 	if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
289 	return emit(w, buf, count);
290 }
291 
292 int
293 spdk_json_write_uint128(struct spdk_json_write_ctx *w, uint64_t low_val, uint64_t high_val)
294 {
295 	char buf[128] = {'\0'};
296 	uint64_t low = low_val, high = high_val;
297 	int count = 0;
298 
299 	if (begin_value(w)) { return fail(w); }
300 
301 	if (high != 0) {
302 		char temp_buf[128] = {'\0'};
303 		uint64_t seg;
304 		unsigned __int128 total = (unsigned __int128)low +
305 					  ((unsigned __int128)high << 64);
306 
307 		while (total) {
308 			seg = total % 10000000000;
309 			total = total / 10000000000;
310 			if (total) {
311 				count = snprintf(temp_buf, 128, "%010" PRIu64 "%s", seg, buf);
312 			} else {
313 				count = snprintf(temp_buf, 128, "%" PRIu64 "%s", seg, buf);
314 			}
315 
316 			if (count <= 0 || (size_t)count >= sizeof(temp_buf)) {
317 				return fail(w);
318 			}
319 
320 			snprintf(buf, 128, "%s", temp_buf);
321 		}
322 	} else {
323 		count = snprintf(buf, sizeof(buf), "%" PRIu64, low);
324 
325 		if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); }
326 	}
327 
328 	return emit(w, buf, count);
329 }
330 
331 int
332 spdk_json_write_named_uint128(struct spdk_json_write_ctx *w, const char *name,
333 			      uint64_t low_val, uint64_t high_val)
334 {
335 	int rc = spdk_json_write_name(w, name);
336 
337 	return rc ? rc : spdk_json_write_uint128(w, low_val, high_val);
338 }
339 
340 static void
341 write_hex_2(void *dest, uint8_t val)
342 {
343 	char *p = dest;
344 	char hex[] = "0123456789ABCDEF";
345 
346 	p[0] = hex[val >> 4];
347 	p[1] = hex[val & 0xf];
348 }
349 
350 static void
351 write_hex_4(void *dest, uint16_t val)
352 {
353 	write_hex_2(dest, (uint8_t)(val >> 8));
354 	write_hex_2((char *)dest + 2, (uint8_t)(val & 0xff));
355 }
356 
357 static inline int
358 write_codepoint(struct spdk_json_write_ctx *w, uint32_t codepoint)
359 {
360 	static const uint8_t escapes[] = {
361 		['\b'] = 'b',
362 		['\f'] = 'f',
363 		['\n'] = 'n',
364 		['\r'] = 'r',
365 		['\t'] = 't',
366 		['"'] = '"',
367 		['\\'] = '\\',
368 		/*
369 		 * Forward slash (/) is intentionally not converted to an escape
370 		 *  (it is valid unescaped).
371 		 */
372 	};
373 	uint16_t high, low;
374 	char out[13];
375 	size_t out_len;
376 
377 	if (codepoint < sizeof(escapes) && escapes[codepoint]) {
378 		out[0] = '\\';
379 		out[1] = escapes[codepoint];
380 		out_len = 2;
381 	} else if (codepoint >= 0x20 && codepoint < 0x7F) {
382 		/*
383 		 * Encode plain ASCII directly (except 0x7F, since it is really
384 		 *  a control character, despite the JSON spec not considering it one).
385 		 */
386 		out[0] = (uint8_t)codepoint;
387 		out_len = 1;
388 	} else if (codepoint < 0x10000) {
389 		out[0] = '\\';
390 		out[1] = 'u';
391 		write_hex_4(&out[2], (uint16_t)codepoint);
392 		out_len = 6;
393 	} else {
394 		utf16_encode_surrogate_pair(codepoint, &high, &low);
395 		out[0] = '\\';
396 		out[1] = 'u';
397 		write_hex_4(&out[2], high);
398 		out[6] = '\\';
399 		out[7] = 'u';
400 		write_hex_4(&out[8], low);
401 		out_len = 12;
402 	}
403 
404 	return emit(w, out, out_len);
405 }
406 
407 static int
408 write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
409 {
410 	const uint8_t *p = val;
411 	const uint8_t *end = val + len;
412 
413 	if (emit(w, "\"", 1)) { return fail(w); }
414 
415 	while (p != end) {
416 		int codepoint_len;
417 		uint32_t codepoint;
418 
419 		codepoint_len = utf8_valid(p, end);
420 		switch (codepoint_len) {
421 		case 1:
422 			codepoint = utf8_decode_unsafe_1(p);
423 			break;
424 		case 2:
425 			codepoint = utf8_decode_unsafe_2(p);
426 			break;
427 		case 3:
428 			codepoint = utf8_decode_unsafe_3(p);
429 			break;
430 		case 4:
431 			codepoint = utf8_decode_unsafe_4(p);
432 			break;
433 		default:
434 			return fail(w);
435 		}
436 
437 		if (write_codepoint(w, codepoint)) { return fail(w); }
438 		p += codepoint_len;
439 	}
440 
441 	return emit(w, "\"", 1);
442 }
443 
444 static int
445 write_string_or_name_utf16le(struct spdk_json_write_ctx *w, const uint16_t *val, size_t len)
446 {
447 	const uint16_t *p = val;
448 	const uint16_t *end = val + len;
449 
450 	if (emit(w, "\"", 1)) { return fail(w); }
451 
452 	while (p != end) {
453 		int codepoint_len;
454 		uint32_t codepoint;
455 
456 		codepoint_len = utf16le_valid(p, end);
457 		switch (codepoint_len) {
458 		case 1:
459 			codepoint = from_le16(&p[0]);
460 			break;
461 		case 2:
462 			codepoint = utf16_decode_surrogate_pair(from_le16(&p[0]), from_le16(&p[1]));
463 			break;
464 		default:
465 			return fail(w);
466 		}
467 
468 		if (write_codepoint(w, codepoint)) { return fail(w); }
469 		p += codepoint_len;
470 	}
471 
472 	return emit(w, "\"", 1);
473 }
474 
475 int
476 spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len)
477 {
478 	if (begin_value(w)) { return fail(w); }
479 	return write_string_or_name(w, val, len);
480 }
481 
482 int
483 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
484 {
485 	return spdk_json_write_string_raw(w, val, strlen(val));
486 }
487 
488 int
489 spdk_json_write_string_utf16le_raw(struct spdk_json_write_ctx *w, const uint16_t *val, size_t len)
490 {
491 	if (begin_value(w)) { return fail(w); }
492 	return write_string_or_name_utf16le(w, val, len);
493 }
494 
495 int
496 spdk_json_write_string_utf16le(struct spdk_json_write_ctx *w, const uint16_t *val)
497 {
498 	const uint16_t *p;
499 	size_t len;
500 
501 	for (len = 0, p = val; *p; p++) {
502 		len++;
503 	}
504 
505 	return spdk_json_write_string_utf16le_raw(w, val, len);
506 }
507 
508 int
509 spdk_json_write_string_fmt(struct spdk_json_write_ctx *w, const char *fmt, ...)
510 {
511 	va_list args;
512 	int rc;
513 
514 	va_start(args, fmt);
515 	rc = spdk_json_write_string_fmt_v(w, fmt, args);
516 	va_end(args);
517 
518 	return rc;
519 }
520 
521 int
522 spdk_json_write_string_fmt_v(struct spdk_json_write_ctx *w, const char *fmt, va_list args)
523 {
524 	char *s;
525 	int rc;
526 
527 	s = spdk_vsprintf_alloc(fmt, args);
528 	if (s == NULL) {
529 		return -1;
530 	}
531 
532 	rc = spdk_json_write_string(w, s);
533 	free(s);
534 	return rc;
535 }
536 
537 int
538 spdk_json_write_bytearray(struct spdk_json_write_ctx *w, const void *val, size_t len)
539 {
540 	const uint8_t *v = val;
541 	size_t i;
542 	char *s;
543 	int rc;
544 
545 	s = malloc(2 * len + 1);
546 	if (s == NULL) {
547 		return -1;
548 	}
549 
550 	for (i = 0; i < len; ++i) {
551 		write_hex_2(&s[2 * i], *v++);
552 	}
553 	s[2 * len] = '\0';
554 
555 	rc = spdk_json_write_string(w, s);
556 	free(s);
557 	return rc;
558 }
559 
560 int
561 spdk_json_write_array_begin(struct spdk_json_write_ctx *w)
562 {
563 	if (begin_value(w)) { return fail(w); }
564 	w->first_value = true;
565 	w->new_indent = true;
566 	w->indent++;
567 	if (emit(w, "[", 1)) { return fail(w); }
568 	return 0;
569 }
570 
571 int
572 spdk_json_write_array_end(struct spdk_json_write_ctx *w)
573 {
574 	w->first_value = false;
575 	if (w->indent == 0) { return fail(w); }
576 	w->indent--;
577 	if (!w->new_indent) {
578 		if (emit_fmt(w, "\n", 1)) { return fail(w); }
579 		if (emit_indent(w)) { return fail(w); }
580 	}
581 	w->new_indent = false;
582 	return emit(w, "]", 1);
583 }
584 
585 int
586 spdk_json_write_object_begin(struct spdk_json_write_ctx *w)
587 {
588 	if (begin_value(w)) { return fail(w); }
589 	w->first_value = true;
590 	w->new_indent = true;
591 	w->indent++;
592 	if (emit(w, "{", 1)) { return fail(w); }
593 	return 0;
594 }
595 
596 int
597 spdk_json_write_object_end(struct spdk_json_write_ctx *w)
598 {
599 	w->first_value = false;
600 	w->indent--;
601 	if (!w->new_indent) {
602 		if (emit_fmt(w, "\n", 1)) { return fail(w); }
603 		if (emit_indent(w)) { return fail(w); }
604 	}
605 	w->new_indent = false;
606 	return emit(w, "}", 1);
607 }
608 
609 int
610 spdk_json_write_name_raw(struct spdk_json_write_ctx *w, const char *name, size_t len)
611 {
612 	/* TODO: check that container is an object */
613 	if (begin_value(w)) { return fail(w); }
614 	if (write_string_or_name(w, name, len)) { return fail(w); }
615 	w->first_value = true;
616 	if (emit(w, ":", 1)) { return fail(w); }
617 	return emit_fmt(w, " ", 1);
618 }
619 
620 int
621 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
622 {
623 	return spdk_json_write_name_raw(w, name, strlen(name));
624 }
625 
626 int
627 spdk_json_write_val(struct spdk_json_write_ctx *w, const struct spdk_json_val *val)
628 {
629 	size_t num_values, i;
630 
631 	switch (val->type) {
632 	case SPDK_JSON_VAL_NUMBER:
633 		return spdk_json_write_val_raw(w, val->start, val->len);
634 
635 	case SPDK_JSON_VAL_STRING:
636 		return spdk_json_write_string_raw(w, val->start, val->len);
637 
638 	case SPDK_JSON_VAL_NAME:
639 		return spdk_json_write_name_raw(w, val->start, val->len);
640 
641 	case SPDK_JSON_VAL_TRUE:
642 		return spdk_json_write_bool(w, true);
643 
644 	case SPDK_JSON_VAL_FALSE:
645 		return spdk_json_write_bool(w, false);
646 
647 	case SPDK_JSON_VAL_NULL:
648 		return spdk_json_write_null(w);
649 
650 	case SPDK_JSON_VAL_ARRAY_BEGIN:
651 	case SPDK_JSON_VAL_OBJECT_BEGIN:
652 		num_values = val[0].len;
653 
654 		if (val[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
655 			if (spdk_json_write_object_begin(w)) {
656 				return fail(w);
657 			}
658 		} else {
659 			if (spdk_json_write_array_begin(w)) {
660 				return fail(w);
661 			}
662 		}
663 
664 		/* Loop up to and including the _END value */
665 		for (i = 0; i < num_values + 1;) {
666 			if (spdk_json_write_val(w, &val[i + 1])) {
667 				return fail(w);
668 			}
669 			if (val[i + 1].type == SPDK_JSON_VAL_ARRAY_BEGIN ||
670 			    val[i + 1].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
671 				i += val[i + 1].len + 2;
672 			} else {
673 				i++;
674 			}
675 		}
676 		return 0;
677 
678 	case SPDK_JSON_VAL_ARRAY_END:
679 		return spdk_json_write_array_end(w);
680 
681 	case SPDK_JSON_VAL_OBJECT_END:
682 		return spdk_json_write_object_end(w);
683 
684 	case SPDK_JSON_VAL_INVALID:
685 		/* Handle INVALID to make the compiler happy (and catch other unhandled types) */
686 		return fail(w);
687 	}
688 
689 	return fail(w);
690 }
691 
692 int spdk_json_write_named_null(struct spdk_json_write_ctx *w, const char *name)
693 {
694 	int rc = spdk_json_write_name(w, name);
695 	return rc ? rc : spdk_json_write_null(w);
696 }
697 
698 int spdk_json_write_named_bool(struct spdk_json_write_ctx *w, const char *name, bool val)
699 {
700 	int rc = spdk_json_write_name(w, name);
701 
702 	return rc ? rc : spdk_json_write_bool(w, val);
703 }
704 
705 int spdk_json_write_named_uint8(struct spdk_json_write_ctx *w, const char *name, uint8_t val)
706 {
707 	int rc = spdk_json_write_name(w, name);
708 
709 	return rc ? rc : spdk_json_write_uint8(w, val);
710 }
711 
712 int spdk_json_write_named_uint16(struct spdk_json_write_ctx *w, const char *name, uint16_t val)
713 {
714 	int rc = spdk_json_write_name(w, name);
715 
716 	return rc ? rc : spdk_json_write_uint16(w, val);
717 }
718 
719 int spdk_json_write_named_int32(struct spdk_json_write_ctx *w, const char *name, int32_t val)
720 {
721 	int rc = spdk_json_write_name(w, name);
722 
723 	return rc ? rc : spdk_json_write_int32(w, val);
724 }
725 
726 int spdk_json_write_named_uint32(struct spdk_json_write_ctx *w, const char *name, uint32_t val)
727 {
728 	int rc = spdk_json_write_name(w, name);
729 
730 	return rc ? rc : spdk_json_write_uint32(w, val);
731 }
732 
733 int spdk_json_write_named_int64(struct spdk_json_write_ctx *w, const char *name, int64_t val)
734 {
735 	int rc = spdk_json_write_name(w, name);
736 
737 	return rc ? rc : spdk_json_write_int64(w, val);
738 }
739 
740 int spdk_json_write_named_uint64(struct spdk_json_write_ctx *w, const char *name, uint64_t val)
741 {
742 	int rc = spdk_json_write_name(w, name);
743 
744 	return rc ? rc : spdk_json_write_uint64(w, val);
745 }
746 
747 int spdk_json_write_named_string(struct spdk_json_write_ctx *w, const char *name, const char *val)
748 {
749 	int rc = spdk_json_write_name(w, name);
750 
751 	return rc ? rc : spdk_json_write_string(w, val);
752 }
753 
754 int spdk_json_write_named_string_fmt(struct spdk_json_write_ctx *w, const char *name,
755 				     const char *fmt, ...)
756 {
757 	va_list args;
758 	int rc;
759 
760 	va_start(args, fmt);
761 	rc = spdk_json_write_named_string_fmt_v(w, name, fmt, args);
762 	va_end(args);
763 
764 	return rc;
765 }
766 
767 int spdk_json_write_named_string_fmt_v(struct spdk_json_write_ctx *w, const char *name,
768 				       const char *fmt, va_list args)
769 {
770 	char *s;
771 	int rc;
772 
773 	rc = spdk_json_write_name(w, name);
774 	if (rc) {
775 		return rc;
776 	}
777 
778 	s = spdk_vsprintf_alloc(fmt, args);
779 
780 	if (s == NULL) {
781 		return -1;
782 	}
783 
784 	rc = spdk_json_write_string(w, s);
785 	free(s);
786 	return rc;
787 }
788 
789 int
790 spdk_json_write_named_bytearray(struct spdk_json_write_ctx *w, const char *name, const void *val,
791 				size_t len)
792 {
793 	int rc = spdk_json_write_name(w, name);
794 
795 	return rc ? rc : spdk_json_write_bytearray(w, val, len);
796 }
797 
798 int spdk_json_write_named_array_begin(struct spdk_json_write_ctx *w, const char *name)
799 {
800 	int rc = spdk_json_write_name(w, name);
801 
802 	return rc ? rc : spdk_json_write_array_begin(w);
803 }
804 
805 int spdk_json_write_named_object_begin(struct spdk_json_write_ctx *w, const char *name)
806 {
807 	int rc = spdk_json_write_name(w, name);
808 
809 	return rc ? rc : spdk_json_write_object_begin(w);
810 }
811