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