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