]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/json/json_write.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / spdk / lib / json / json_write.c
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 "json_internal.h"
35
36 struct spdk_json_write_ctx {
37 spdk_json_write_cb write_cb;
38 void *cb_ctx;
39 uint32_t flags;
40 uint32_t indent;
41 bool new_indent;
42 bool first_value;
43 bool failed;
44 size_t buf_filled;
45 uint8_t buf[4096];
46 };
47
48 static int emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size);
49
50 static int
51 fail(struct spdk_json_write_ctx *w)
52 {
53 w->failed = true;
54 return -1;
55 }
56
57 static int
58 flush_buf(struct spdk_json_write_ctx *w)
59 {
60 int rc;
61
62 rc = w->write_cb(w->cb_ctx, w->buf, w->buf_filled);
63 if (rc != 0) {
64 return fail(w);
65 }
66
67 w->buf_filled = 0;
68
69 return 0;
70 }
71
72 struct spdk_json_write_ctx *
73 spdk_json_write_begin(spdk_json_write_cb write_cb, void *cb_ctx, uint32_t flags)
74 {
75 struct spdk_json_write_ctx *w;
76
77 w = calloc(1, sizeof(*w));
78 if (w == NULL) {
79 return w;
80 }
81
82 w->write_cb = write_cb;
83 w->cb_ctx = cb_ctx;
84 w->flags = flags;
85 w->indent = 0;
86 w->new_indent = false;
87 w->first_value = true;
88 w->failed = false;
89 w->buf_filled = 0;
90
91 return w;
92 }
93
94 int
95 spdk_json_write_end(struct spdk_json_write_ctx *w)
96 {
97 bool failed;
98 int rc;
99
100 if (w == NULL) {
101 return 0;
102 }
103
104 failed = w->failed;
105
106 rc = flush_buf(w);
107 if (rc != 0) {
108 failed = true;
109 }
110
111 free(w);
112
113 return failed ? -1 : 0;
114 }
115
116 static inline int
117 emit(struct spdk_json_write_ctx *w, const void *data, size_t size)
118 {
119 size_t buf_remain = sizeof(w->buf) - w->buf_filled;
120
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);
124 }
125
126 /* Copy the new data into buf. */
127 memcpy(w->buf + w->buf_filled, data, size);
128 w->buf_filled += size;
129 return 0;
130 }
131
132 static int
133 emit_buf_full(struct spdk_json_write_ctx *w, const void *data, size_t size)
134 {
135 size_t buf_remain = sizeof(w->buf) - w->buf_filled;
136 int rc;
137
138 assert(size > buf_remain);
139
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;
143
144 rc = flush_buf(w);
145 if (rc != 0) {
146 return fail(w);
147 }
148
149 /* Recurse to emit the rest of the data. */
150 return emit(w, data + buf_remain, size - buf_remain);
151 }
152
153 static int
154 emit_fmt(struct spdk_json_write_ctx *w, const void *data, size_t size)
155 {
156 if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) {
157 return emit(w, data, size);
158 }
159 return 0;
160 }
161
162 static int
163 emit_indent(struct spdk_json_write_ctx *w)
164 {
165 uint32_t i;
166
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);
170 }
171 }
172 return 0;
173 }
174
175 static int
176 begin_value(struct spdk_json_write_ctx *w)
177 {
178 // TODO: check for value state
179 if (w->new_indent) {
180 if (emit_fmt(w, "\n", 1)) return fail(w);
181 if (emit_indent(w)) return fail(w);
182 }
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);
187 }
188 w->first_value = false;
189 w->new_indent = false;
190 return 0;
191 }
192
193 int
194 spdk_json_write_val_raw(struct spdk_json_write_ctx *w, const void *data, size_t len)
195 {
196 if (begin_value(w)) return fail(w);
197 return emit(w, data, len);
198 }
199
200 int
201 spdk_json_write_null(struct spdk_json_write_ctx *w)
202 {
203 if (begin_value(w)) return fail(w);
204 return emit(w, "null", 4);
205 }
206
207 int
208 spdk_json_write_bool(struct spdk_json_write_ctx *w, bool val)
209 {
210 if (begin_value(w)) return fail(w);
211 if (val) {
212 return emit(w, "true", 4);
213 } else {
214 return emit(w, "false", 5);
215 }
216 }
217
218 int
219 spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val)
220 {
221 char buf[32];
222 int count;
223
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);
228 }
229
230 int
231 spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val)
232 {
233 char buf[32];
234 int count;
235
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);
240 }
241
242 int
243 spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val)
244 {
245 char buf[32];
246 int count;
247
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);
252 }
253
254 int
255 spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val)
256 {
257 char buf[32];
258 int count;
259
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);
264 }
265
266 static void
267 write_hex_4(void *dest, uint16_t val)
268 {
269 uint8_t *p = dest;
270 char hex[] = "0123456789ABCDEF";
271
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];
276 }
277
278 static int
279 write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
280 {
281 const uint8_t *p = val;
282 const uint8_t *end = val + len;
283 static const uint8_t escapes[] = {
284 ['\b'] = 'b',
285 ['\f'] = 'f',
286 ['\n'] = 'n',
287 ['\r'] = 'r',
288 ['\t'] = 't',
289 ['"'] = '"',
290 ['\\'] = '\\',
291 /*
292 * Forward slash (/) is intentionally not converted to an escape
293 * (it is valid unescaped).
294 */
295 };
296
297 if (emit(w, "\"", 1)) return fail(w);
298
299 while (p != end) {
300 int codepoint_len;
301 uint32_t codepoint;
302 uint16_t high, low;
303 char out[13];
304 size_t out_len;
305
306 codepoint_len = utf8_valid(p, end);
307 switch (codepoint_len) {
308 case 1:
309 codepoint = utf8_decode_unsafe_1(p);
310 break;
311 case 2:
312 codepoint = utf8_decode_unsafe_2(p);
313 break;
314 case 3:
315 codepoint = utf8_decode_unsafe_3(p);
316 break;
317 case 4:
318 codepoint = utf8_decode_unsafe_4(p);
319 break;
320 default:
321 return fail(w);
322 }
323
324 if (codepoint < sizeof(escapes) && escapes[codepoint]) {
325 out[0] = '\\';
326 out[1] = escapes[codepoint];
327 out_len = 2;
328 } else if (codepoint >= 0x20 && codepoint < 0x7F) {
329 /*
330 * Encode plain ASCII directly (except 0x7F, since it is really
331 * a control character, despite the JSON spec not considering it one).
332 */
333 out[0] = (uint8_t)codepoint;
334 out_len = 1;
335 } else if (codepoint < 0x10000) {
336 out[0] = '\\';
337 out[1] = 'u';
338 write_hex_4(&out[2], (uint16_t)codepoint);
339 out_len = 6;
340 } else {
341 utf16_encode_surrogate_pair(codepoint, &high, &low);
342 out[0] = '\\';
343 out[1] = 'u';
344 write_hex_4(&out[2], high);
345 out[6] = '\\';
346 out[7] = 'u';
347 write_hex_4(&out[8], low);
348 out_len = 12;
349 }
350
351 if (emit(w, out, out_len)) return fail(w);
352 p += codepoint_len;
353 }
354
355 return emit(w, "\"", 1);
356 }
357
358 int
359 spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len)
360 {
361 if (begin_value(w)) return fail(w);
362 return write_string_or_name(w, val, len);
363 }
364
365 int
366 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val)
367 {
368 return spdk_json_write_string_raw(w, val, strlen(val));
369 }
370
371 int
372 spdk_json_write_string_fmt(struct spdk_json_write_ctx *w, const char *fmt, ...)
373 {
374 char *s;
375 va_list args;
376 int rc;
377
378 va_start(args, fmt);
379 s = spdk_vsprintf_alloc(fmt, args);
380 va_end(args);
381
382 if (s == NULL) {
383 return -1;
384 }
385
386 rc = spdk_json_write_string(w, s);
387 free(s);
388 return rc;
389 }
390
391 int
392 spdk_json_write_array_begin(struct spdk_json_write_ctx *w)
393 {
394 if (begin_value(w)) return fail(w);
395 w->first_value = true;
396 w->new_indent = true;
397 w->indent++;
398 if (emit(w, "[", 1)) return fail(w);
399 return 0;
400 }
401
402 int
403 spdk_json_write_array_end(struct spdk_json_write_ctx *w)
404 {
405 w->first_value = false;
406 if (w->indent == 0) return fail(w);
407 w->indent--;
408 if (!w->new_indent) {
409 if (emit_fmt(w, "\n", 1)) return fail(w);
410 if (emit_indent(w)) return fail(w);
411 }
412 w->new_indent = false;
413 return emit(w, "]", 1);
414 }
415
416 int
417 spdk_json_write_object_begin(struct spdk_json_write_ctx *w)
418 {
419 if (begin_value(w)) return fail(w);
420 w->first_value = true;
421 w->new_indent = true;
422 w->indent++;
423 if (emit(w, "{", 1)) return fail(w);
424 return 0;
425 }
426
427 int
428 spdk_json_write_object_end(struct spdk_json_write_ctx *w)
429 {
430 w->first_value = false;
431 w->indent--;
432 if (!w->new_indent) {
433 if (emit_fmt(w, "\n", 1)) return fail(w);
434 if (emit_indent(w)) return fail(w);
435 }
436 w->new_indent = false;
437 return emit(w, "}", 1);
438 }
439
440 int
441 spdk_json_write_name_raw(struct spdk_json_write_ctx *w, const char *name, size_t len)
442 {
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);
449 }
450
451 int
452 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name)
453 {
454 return spdk_json_write_name_raw(w, name, strlen(name));
455 }
456
457 int
458 spdk_json_write_val(struct spdk_json_write_ctx *w, const struct spdk_json_val *val)
459 {
460 size_t num_values, i;
461
462 switch (val->type) {
463 case SPDK_JSON_VAL_NUMBER:
464 return spdk_json_write_val_raw(w, val->start, val->len);
465
466 case SPDK_JSON_VAL_STRING:
467 return spdk_json_write_string_raw(w, val->start, val->len);
468
469 case SPDK_JSON_VAL_NAME:
470 return spdk_json_write_name_raw(w, val->start, val->len);
471
472 case SPDK_JSON_VAL_TRUE:
473 return spdk_json_write_bool(w, true);
474
475 case SPDK_JSON_VAL_FALSE:
476 return spdk_json_write_bool(w, false);
477
478 case SPDK_JSON_VAL_NULL:
479 return spdk_json_write_null(w);
480
481 case SPDK_JSON_VAL_ARRAY_BEGIN:
482 case SPDK_JSON_VAL_OBJECT_BEGIN:
483 num_values = val[0].len;
484
485 if (val[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
486 if (spdk_json_write_object_begin(w)) {
487 return fail(w);
488 }
489 } else {
490 if (spdk_json_write_array_begin(w)) {
491 return fail(w);
492 }
493 }
494
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])) {
498 return fail(w);
499 }
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;
503 } else {
504 i++;
505 }
506 }
507 return 0;
508
509 case SPDK_JSON_VAL_ARRAY_END:
510 return spdk_json_write_array_end(w);
511
512 case SPDK_JSON_VAL_OBJECT_END:
513 return spdk_json_write_object_end(w);
514
515 case SPDK_JSON_VAL_INVALID:
516 // Handle INVALID to make the compiler happy (and catch other unhandled types)
517 return fail(w);
518 }
519
520 return fail(w);
521 }