4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "json_internal.h"
36 struct spdk_json_write_ctx
{
37 spdk_json_write_cb write_cb
;
48 static int emit_buf_full(struct spdk_json_write_ctx
*w
, const void *data
, size_t size
);
51 fail(struct spdk_json_write_ctx
*w
)
58 flush_buf(struct spdk_json_write_ctx
*w
)
62 rc
= w
->write_cb(w
->cb_ctx
, w
->buf
, w
->buf_filled
);
72 struct spdk_json_write_ctx
*
73 spdk_json_write_begin(spdk_json_write_cb write_cb
, void *cb_ctx
, uint32_t flags
)
75 struct spdk_json_write_ctx
*w
;
77 w
= calloc(1, sizeof(*w
));
82 w
->write_cb
= write_cb
;
86 w
->new_indent
= false;
87 w
->first_value
= true;
95 spdk_json_write_end(struct spdk_json_write_ctx
*w
)
113 return failed
? -1 : 0;
117 emit(struct spdk_json_write_ctx
*w
, const void *data
, size_t size
)
119 size_t buf_remain
= sizeof(w
->buf
) - w
->buf_filled
;
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
);
126 /* Copy the new data into buf. */
127 memcpy(w
->buf
+ w
->buf_filled
, data
, size
);
128 w
->buf_filled
+= size
;
133 emit_buf_full(struct spdk_json_write_ctx
*w
, const void *data
, size_t size
)
135 size_t buf_remain
= sizeof(w
->buf
) - w
->buf_filled
;
138 assert(size
> buf_remain
);
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
;
149 /* Recurse to emit the rest of the data. */
150 return emit(w
, data
+ buf_remain
, size
- buf_remain
);
154 emit_fmt(struct spdk_json_write_ctx
*w
, const void *data
, size_t size
)
156 if (w
->flags
& SPDK_JSON_WRITE_FLAG_FORMATTED
) {
157 return emit(w
, data
, size
);
163 emit_indent(struct spdk_json_write_ctx
*w
)
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
);
176 begin_value(struct spdk_json_write_ctx
*w
)
178 // TODO: check for value state
180 if (emit_fmt(w
, "\n", 1)) return fail(w
);
181 if (emit_indent(w
)) return fail(w
);
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
);
188 w
->first_value
= false;
189 w
->new_indent
= false;
194 spdk_json_write_val_raw(struct spdk_json_write_ctx
*w
, const void *data
, size_t len
)
196 if (begin_value(w
)) return fail(w
);
197 return emit(w
, data
, len
);
201 spdk_json_write_null(struct spdk_json_write_ctx
*w
)
203 if (begin_value(w
)) return fail(w
);
204 return emit(w
, "null", 4);
208 spdk_json_write_bool(struct spdk_json_write_ctx
*w
, bool val
)
210 if (begin_value(w
)) return fail(w
);
212 return emit(w
, "true", 4);
214 return emit(w
, "false", 5);
219 spdk_json_write_int32(struct spdk_json_write_ctx
*w
, int32_t val
)
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
);
231 spdk_json_write_uint32(struct spdk_json_write_ctx
*w
, uint32_t val
)
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
);
243 spdk_json_write_int64(struct spdk_json_write_ctx
*w
, int64_t val
)
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
);
255 spdk_json_write_uint64(struct spdk_json_write_ctx
*w
, uint64_t val
)
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
);
267 write_hex_4(void *dest
, uint16_t val
)
270 char hex
[] = "0123456789ABCDEF";
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];
279 write_string_or_name(struct spdk_json_write_ctx
*w
, const char *val
, size_t len
)
281 const uint8_t *p
= val
;
282 const uint8_t *end
= val
+ len
;
283 static const uint8_t escapes
[] = {
292 * Forward slash (/) is intentionally not converted to an escape
293 * (it is valid unescaped).
297 if (emit(w
, "\"", 1)) return fail(w
);
306 codepoint_len
= utf8_valid(p
, end
);
307 switch (codepoint_len
) {
309 codepoint
= utf8_decode_unsafe_1(p
);
312 codepoint
= utf8_decode_unsafe_2(p
);
315 codepoint
= utf8_decode_unsafe_3(p
);
318 codepoint
= utf8_decode_unsafe_4(p
);
324 if (codepoint
< sizeof(escapes
) && escapes
[codepoint
]) {
326 out
[1] = escapes
[codepoint
];
328 } else if (codepoint
>= 0x20 && codepoint
< 0x7F) {
330 * Encode plain ASCII directly (except 0x7F, since it is really
331 * a control character, despite the JSON spec not considering it one).
333 out
[0] = (uint8_t)codepoint
;
335 } else if (codepoint
< 0x10000) {
338 write_hex_4(&out
[2], (uint16_t)codepoint
);
341 utf16_encode_surrogate_pair(codepoint
, &high
, &low
);
344 write_hex_4(&out
[2], high
);
347 write_hex_4(&out
[8], low
);
351 if (emit(w
, out
, out_len
)) return fail(w
);
355 return emit(w
, "\"", 1);
359 spdk_json_write_string_raw(struct spdk_json_write_ctx
*w
, const char *val
, size_t len
)
361 if (begin_value(w
)) return fail(w
);
362 return write_string_or_name(w
, val
, len
);
366 spdk_json_write_string(struct spdk_json_write_ctx
*w
, const char *val
)
368 return spdk_json_write_string_raw(w
, val
, strlen(val
));
372 spdk_json_write_string_fmt(struct spdk_json_write_ctx
*w
, const char *fmt
, ...)
379 s
= spdk_vsprintf_alloc(fmt
, args
);
386 rc
= spdk_json_write_string(w
, s
);
392 spdk_json_write_array_begin(struct spdk_json_write_ctx
*w
)
394 if (begin_value(w
)) return fail(w
);
395 w
->first_value
= true;
396 w
->new_indent
= true;
398 if (emit(w
, "[", 1)) return fail(w
);
403 spdk_json_write_array_end(struct spdk_json_write_ctx
*w
)
405 w
->first_value
= false;
406 if (w
->indent
== 0) return fail(w
);
408 if (!w
->new_indent
) {
409 if (emit_fmt(w
, "\n", 1)) return fail(w
);
410 if (emit_indent(w
)) return fail(w
);
412 w
->new_indent
= false;
413 return emit(w
, "]", 1);
417 spdk_json_write_object_begin(struct spdk_json_write_ctx
*w
)
419 if (begin_value(w
)) return fail(w
);
420 w
->first_value
= true;
421 w
->new_indent
= true;
423 if (emit(w
, "{", 1)) return fail(w
);
428 spdk_json_write_object_end(struct spdk_json_write_ctx
*w
)
430 w
->first_value
= false;
432 if (!w
->new_indent
) {
433 if (emit_fmt(w
, "\n", 1)) return fail(w
);
434 if (emit_indent(w
)) return fail(w
);
436 w
->new_indent
= false;
437 return emit(w
, "}", 1);
441 spdk_json_write_name_raw(struct spdk_json_write_ctx
*w
, const char *name
, size_t len
)
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);
452 spdk_json_write_name(struct spdk_json_write_ctx
*w
, const char *name
)
454 return spdk_json_write_name_raw(w
, name
, strlen(name
));
458 spdk_json_write_val(struct spdk_json_write_ctx
*w
, const struct spdk_json_val
*val
)
460 size_t num_values
, i
;
463 case SPDK_JSON_VAL_NUMBER
:
464 return spdk_json_write_val_raw(w
, val
->start
, val
->len
);
466 case SPDK_JSON_VAL_STRING
:
467 return spdk_json_write_string_raw(w
, val
->start
, val
->len
);
469 case SPDK_JSON_VAL_NAME
:
470 return spdk_json_write_name_raw(w
, val
->start
, val
->len
);
472 case SPDK_JSON_VAL_TRUE
:
473 return spdk_json_write_bool(w
, true);
475 case SPDK_JSON_VAL_FALSE
:
476 return spdk_json_write_bool(w
, false);
478 case SPDK_JSON_VAL_NULL
:
479 return spdk_json_write_null(w
);
481 case SPDK_JSON_VAL_ARRAY_BEGIN
:
482 case SPDK_JSON_VAL_OBJECT_BEGIN
:
483 num_values
= val
[0].len
;
485 if (val
[0].type
== SPDK_JSON_VAL_OBJECT_BEGIN
) {
486 if (spdk_json_write_object_begin(w
)) {
490 if (spdk_json_write_array_begin(w
)) {
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])) {
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;
509 case SPDK_JSON_VAL_ARRAY_END
:
510 return spdk_json_write_array_end(w
);
512 case SPDK_JSON_VAL_OBJECT_END
:
513 return spdk_json_write_object_end(w
);
515 case SPDK_JSON_VAL_INVALID
:
516 // Handle INVALID to make the compiler happy (and catch other unhandled types)