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 }; 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 64 return w; 65 } 66 67 int 68 spdk_json_write_end(struct spdk_json_write_ctx *w) 69 { 70 bool failed; 71 72 if (w == NULL) { 73 return 0; 74 } 75 76 failed = w->failed; 77 78 free(w); 79 80 return failed ? -1 : 0; 81 } 82 83 static int 84 fail(struct spdk_json_write_ctx *w) 85 { 86 w->failed = true; 87 return -1; 88 } 89 90 static int 91 emit(struct spdk_json_write_ctx *w, const void *data, size_t size) 92 { 93 int rc; 94 95 rc = w->write_cb(w->cb_ctx, data, size); 96 if (rc != 0) { 97 return fail(w); 98 } 99 return 0; 100 } 101 102 static int 103 emit_fmt(struct spdk_json_write_ctx *w, const void *data, size_t size) 104 { 105 if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) { 106 return emit(w, data, size); 107 } 108 return 0; 109 } 110 111 static int 112 emit_indent(struct spdk_json_write_ctx *w) 113 { 114 uint32_t i; 115 116 if (w->flags & SPDK_JSON_WRITE_FLAG_FORMATTED) { 117 for (i = 0; i < w->indent; i++) { 118 if (emit(w, " ", 2)) return fail(w); 119 } 120 } 121 return 0; 122 } 123 124 static int 125 begin_value(struct spdk_json_write_ctx *w) 126 { 127 // TODO: check for value state 128 if (w->new_indent) { 129 if (emit_fmt(w, "\n", 1)) return fail(w); 130 if (emit_indent(w)) return fail(w); 131 } 132 if (!w->first_value) { 133 if (emit(w, ",", 1)) return fail(w); 134 if (emit_fmt(w, "\n", 1)) return fail(w); 135 if (emit_indent(w)) return fail(w); 136 } 137 w->first_value = false; 138 w->new_indent = false; 139 return 0; 140 } 141 142 int 143 spdk_json_write_val_raw(struct spdk_json_write_ctx *w, const void *data, size_t len) 144 { 145 if (begin_value(w)) return fail(w); 146 return emit(w, data, len); 147 } 148 149 int 150 spdk_json_write_null(struct spdk_json_write_ctx *w) 151 { 152 if (begin_value(w)) return fail(w); 153 return emit(w, "null", 4); 154 } 155 156 int 157 spdk_json_write_bool(struct spdk_json_write_ctx *w, bool val) 158 { 159 if (begin_value(w)) return fail(w); 160 if (val) { 161 return emit(w, "true", 4); 162 } else { 163 return emit(w, "false", 5); 164 } 165 } 166 167 int 168 spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val) 169 { 170 char buf[32]; 171 int count; 172 173 if (begin_value(w)) return fail(w); 174 count = snprintf(buf, sizeof(buf), "%" PRId32, val); 175 if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w); 176 return emit(w, buf, count); 177 } 178 179 int 180 spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val) 181 { 182 char buf[32]; 183 int count; 184 185 if (begin_value(w)) return fail(w); 186 count = snprintf(buf, sizeof(buf), "%" PRIu32, val); 187 if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w); 188 return emit(w, buf, count); 189 } 190 191 int 192 spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val) 193 { 194 char buf[32]; 195 int count; 196 197 if (begin_value(w)) return fail(w); 198 count = snprintf(buf, sizeof(buf), "%" PRId64, val); 199 if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w); 200 return emit(w, buf, count); 201 } 202 203 int 204 spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val) 205 { 206 char buf[32]; 207 int count; 208 209 if (begin_value(w)) return fail(w); 210 count = snprintf(buf, sizeof(buf), "%" PRIu64, val); 211 if (count <= 0 || (size_t)count >= sizeof(buf)) return fail(w); 212 return emit(w, buf, count); 213 } 214 215 static void 216 write_hex_4(void *dest, uint16_t val) 217 { 218 uint8_t *p = dest; 219 char hex[] = "0123456789ABCDEF"; 220 221 p[0] = hex[(val >> 12)]; 222 p[1] = hex[(val >> 8) & 0xF]; 223 p[2] = hex[(val >> 4) & 0xF]; 224 p[3] = hex[val & 0xF]; 225 } 226 227 static int 228 write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len) 229 { 230 const uint8_t *p = val; 231 const uint8_t *end = val + len; 232 static const uint8_t escapes[] = { 233 ['\b'] = 'b', 234 ['\f'] = 'f', 235 ['\n'] = 'n', 236 ['\r'] = 'r', 237 ['\t'] = 't', 238 ['"'] = '"', 239 ['\\'] = '\\', 240 /* 241 * Forward slash (/) is intentionally not converted to an escape 242 * (it is valid unescaped). 243 */ 244 }; 245 246 if (emit(w, "\"", 1)) return fail(w); 247 248 while (p != end) { 249 int codepoint_len; 250 uint32_t codepoint; 251 uint16_t high, low; 252 char out[13]; 253 size_t out_len; 254 255 codepoint_len = utf8_valid(p, end); 256 switch (codepoint_len) { 257 case 1: 258 codepoint = utf8_decode_unsafe_1(p); 259 break; 260 case 2: 261 codepoint = utf8_decode_unsafe_2(p); 262 break; 263 case 3: 264 codepoint = utf8_decode_unsafe_3(p); 265 break; 266 case 4: 267 codepoint = utf8_decode_unsafe_4(p); 268 break; 269 default: 270 return fail(w); 271 } 272 273 if (codepoint < sizeof(escapes) && escapes[codepoint]) { 274 out[0] = '\\'; 275 out[1] = escapes[codepoint]; 276 out_len = 2; 277 } else if (codepoint >= 0x20 && codepoint < 0x7F) { 278 /* 279 * Encode plain ASCII directly (except 0x7F, since it is really 280 * a control character, despite the JSON spec not considering it one). 281 */ 282 out[0] = (uint8_t)codepoint; 283 out_len = 1; 284 } else if (codepoint < 0x10000) { 285 out[0] = '\\'; 286 out[1] = 'u'; 287 write_hex_4(&out[2], (uint16_t)codepoint); 288 out_len = 6; 289 } else { 290 utf16_encode_surrogate_pair(codepoint, &high, &low); 291 out[0] = '\\'; 292 out[1] = 'u'; 293 write_hex_4(&out[2], high); 294 out[6] = '\\'; 295 out[7] = 'u'; 296 write_hex_4(&out[8], low); 297 out_len = 12; 298 } 299 300 if (emit(w, out, out_len)) return fail(w); 301 p += codepoint_len; 302 } 303 304 return emit(w, "\"", 1); 305 } 306 307 int 308 spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len) 309 { 310 if (begin_value(w)) return fail(w); 311 return write_string_or_name(w, val, len); 312 } 313 314 int 315 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val) 316 { 317 return spdk_json_write_string_raw(w, val, strlen(val)); 318 } 319 320 int 321 spdk_json_write_array_begin(struct spdk_json_write_ctx *w) 322 { 323 if (begin_value(w)) return fail(w); 324 w->first_value = true; 325 w->new_indent = true; 326 w->indent++; 327 if (emit(w, "[", 1)) return fail(w); 328 return 0; 329 } 330 331 int 332 spdk_json_write_array_end(struct spdk_json_write_ctx *w) 333 { 334 w->first_value = false; 335 if (w->indent == 0) return fail(w); 336 w->indent--; 337 if (!w->new_indent) { 338 if (emit_fmt(w, "\n", 1)) return fail(w); 339 if (emit_indent(w)) return fail(w); 340 } 341 w->new_indent = false; 342 return emit(w, "]", 1); 343 } 344 345 int 346 spdk_json_write_object_begin(struct spdk_json_write_ctx *w) 347 { 348 if (begin_value(w)) return fail(w); 349 w->first_value = true; 350 w->new_indent = true; 351 w->indent++; 352 if (emit(w, "{", 1)) return fail(w); 353 return 0; 354 } 355 356 int 357 spdk_json_write_object_end(struct spdk_json_write_ctx *w) 358 { 359 w->first_value = false; 360 w->indent--; 361 if (!w->new_indent) { 362 if (emit_fmt(w, "\n", 1)) return fail(w); 363 if (emit_indent(w)) return fail(w); 364 } 365 w->new_indent = false; 366 return emit(w, "}", 1); 367 } 368 369 int 370 spdk_json_write_name_raw(struct spdk_json_write_ctx *w, const char *name, size_t len) 371 { 372 /* TODO: check that container is an object */ 373 if (begin_value(w)) return fail(w); 374 if (write_string_or_name(w, name, len)) return fail(w); 375 w->first_value = true; 376 if (emit(w, ":", 1)) return fail(w); 377 return emit_fmt(w, " ", 1); 378 } 379 380 int 381 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name) 382 { 383 return spdk_json_write_name_raw(w, name, strlen(name)); 384 } 385 386 int 387 spdk_json_write_val(struct spdk_json_write_ctx *w, const struct spdk_json_val *val) 388 { 389 size_t num_values, i; 390 391 switch (val->type) { 392 case SPDK_JSON_VAL_NUMBER: 393 return spdk_json_write_val_raw(w, val->start, val->len); 394 395 case SPDK_JSON_VAL_STRING: 396 return spdk_json_write_string_raw(w, val->start, val->len); 397 398 case SPDK_JSON_VAL_NAME: 399 return spdk_json_write_name_raw(w, val->start, val->len); 400 401 case SPDK_JSON_VAL_TRUE: 402 return spdk_json_write_bool(w, true); 403 404 case SPDK_JSON_VAL_FALSE: 405 return spdk_json_write_bool(w, false); 406 407 case SPDK_JSON_VAL_NULL: 408 return spdk_json_write_null(w); 409 410 case SPDK_JSON_VAL_ARRAY_BEGIN: 411 case SPDK_JSON_VAL_OBJECT_BEGIN: 412 num_values = val[0].len; 413 414 if (val[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) { 415 if (spdk_json_write_object_begin(w)) { 416 return fail(w); 417 } 418 } else { 419 if (spdk_json_write_array_begin(w)) { 420 return fail(w); 421 } 422 } 423 424 // Loop up to and including the _END value 425 for (i = 0; i < num_values + 1;) { 426 if (spdk_json_write_val(w, &val[i + 1])) { 427 return fail(w); 428 } 429 if (val[i + 1].type == SPDK_JSON_VAL_ARRAY_BEGIN || 430 val[i + 1].type == SPDK_JSON_VAL_OBJECT_BEGIN) { 431 i += val[i + 1].len + 2; 432 } else { 433 i++; 434 } 435 } 436 return 0; 437 438 case SPDK_JSON_VAL_ARRAY_END: 439 return spdk_json_write_array_end(w); 440 441 case SPDK_JSON_VAL_OBJECT_END: 442 return spdk_json_write_object_end(w); 443 444 case SPDK_JSON_VAL_INVALID: 445 // Handle INVALID to make the compiler happy (and catch other unhandled types) 446 return fail(w); 447 } 448 449 return fail(w); 450 } 451