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 25 fail(struct spdk_json_write_ctx *w) 26 { 27 w->failed = true; 28 return -1; 29 } 30 31 static int 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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