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