frozen.c (45560B)
1 /* 2 * Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com> 3 * Copyright (c) 2018 Cesanta Software Limited 4 * All rights reserved 5 * 6 * Licensed under the Apache License, Version 2.0 (the ""License""); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an ""AS IS"" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */ 20 21 #include "frozen.h" 22 23 #include <ctype.h> 24 #include <stdarg.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #if !defined(WEAK) 30 #if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32) 31 #define WEAK __attribute__((weak)) 32 #else 33 #define WEAK 34 #endif 35 #endif 36 37 #ifdef _WIN32 38 #undef snprintf 39 #undef vsnprintf 40 #define snprintf cs_win_snprintf 41 #define vsnprintf cs_win_vsnprintf 42 int cs_win_snprintf(char *str, size_t size, const char *format, ...); 43 int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap); 44 #if _MSC_VER >= 1700 45 #include <stdint.h> 46 #else 47 typedef _int64 int64_t; 48 typedef unsigned _int64 uint64_t; 49 #endif 50 #define PRId64 "I64d" 51 #define PRIu64 "I64u" 52 #else /* _WIN32 */ 53 /* <inttypes.h> wants this for C++ */ 54 #ifndef __STDC_FORMAT_MACROS 55 #define __STDC_FORMAT_MACROS 56 #endif 57 #include <inttypes.h> 58 #endif /* _WIN32 */ 59 60 #ifndef INT64_FMT 61 #define INT64_FMT PRId64 62 #endif 63 #ifndef UINT64_FMT 64 #define UINT64_FMT PRIu64 65 #endif 66 67 #ifndef va_copy 68 #define va_copy(x, y) x = y 69 #endif 70 71 #ifndef JSON_ENABLE_ARRAY 72 #define JSON_ENABLE_ARRAY 1 73 #endif 74 75 struct frozen { 76 const char *end; 77 const char *cur; 78 79 const char *cur_name; 80 size_t cur_name_len; 81 82 /* For callback API */ 83 char path[JSON_MAX_PATH_LEN]; 84 size_t path_len; 85 void *callback_data; 86 json_walk_callback_t callback; 87 }; 88 89 struct fstate { 90 const char *ptr; 91 size_t path_len; 92 }; 93 94 #define SET_STATE(fr, ptr, str, len) \ 95 struct fstate fstate = {(ptr), (fr)->path_len}; \ 96 json_append_to_path((fr), (str), (len)); 97 98 #define CALL_BACK(fr, tok, value, len) \ 99 do { \ 100 if ((fr)->callback && \ 101 ((fr)->path_len == 0 || (fr)->path[(fr)->path_len - 1] != '.')) { \ 102 struct json_token t = {(value), (int) (len), (tok)}; \ 103 \ 104 /* Call the callback with the given value and current name */ \ 105 (fr)->callback((fr)->callback_data, (fr)->cur_name, (fr)->cur_name_len, \ 106 (fr)->path, &t); \ 107 \ 108 /* Reset the name */ \ 109 (fr)->cur_name = NULL; \ 110 (fr)->cur_name_len = 0; \ 111 } \ 112 } while (0) 113 114 static int json_append_to_path(struct frozen *f, const char *str, int size) { 115 int n = f->path_len; 116 int left = sizeof(f->path) - n - 1; 117 if (size > left) size = left; 118 memcpy(f->path + n, str, size); 119 f->path[n + size] = '\0'; 120 f->path_len += size; 121 return n; 122 } 123 124 static void json_truncate_path(struct frozen *f, size_t len) { 125 f->path_len = len; 126 f->path[len] = '\0'; 127 } 128 129 static int json_parse_object(struct frozen *f); 130 static int json_parse_value(struct frozen *f); 131 132 #define EXPECT(cond, err_code) \ 133 do { \ 134 if (!(cond)) return (err_code); \ 135 } while (0) 136 137 #define TRY(expr) \ 138 do { \ 139 int _n = expr; \ 140 if (_n < 0) return _n; \ 141 } while (0) 142 143 #define END_OF_STRING (-1) 144 145 static int json_left(const struct frozen *f) { 146 return f->end - f->cur; 147 } 148 149 static int json_isspace(int ch) { 150 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; 151 } 152 153 static void json_skip_whitespaces(struct frozen *f) { 154 while (f->cur < f->end && json_isspace(*f->cur)) f->cur++; 155 } 156 157 static int json_cur(struct frozen *f) { 158 json_skip_whitespaces(f); 159 return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur; 160 } 161 162 static int json_test_and_skip(struct frozen *f, int expected) { 163 int ch = json_cur(f); 164 if (ch == expected) { 165 f->cur++; 166 return 0; 167 } 168 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; 169 } 170 171 static int json_isalpha(int ch) { 172 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); 173 } 174 175 static int json_isdigit(int ch) { 176 return ch >= '0' && ch <= '9'; 177 } 178 179 static int json_isxdigit(int ch) { 180 return json_isdigit(ch) || (ch >= 'a' && ch <= 'f') || 181 (ch >= 'A' && ch <= 'F'); 182 } 183 184 static int json_get_escape_len(const char *s, int len) { 185 switch (*s) { 186 case 'u': 187 return len < 6 ? JSON_STRING_INCOMPLETE 188 : json_isxdigit(s[1]) && json_isxdigit(s[2]) && 189 json_isxdigit(s[3]) && json_isxdigit(s[4]) 190 ? 5 191 : JSON_STRING_INVALID; 192 case '"': 193 case '\\': 194 case '/': 195 case 'b': 196 case 'f': 197 case 'n': 198 case 'r': 199 case 't': 200 return len < 2 ? JSON_STRING_INCOMPLETE : 1; 201 default: 202 return JSON_STRING_INVALID; 203 } 204 } 205 206 /* identifier = letter { letter | digit | '_' } */ 207 static int json_parse_identifier(struct frozen *f) { 208 EXPECT(json_isalpha(json_cur(f)), JSON_STRING_INVALID); 209 { 210 SET_STATE(f, f->cur, "", 0); 211 while (f->cur < f->end && 212 (*f->cur == '_' || json_isalpha(*f->cur) || json_isdigit(*f->cur))) { 213 f->cur++; 214 } 215 json_truncate_path(f, fstate.path_len); 216 CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr); 217 } 218 return 0; 219 } 220 221 static int json_get_utf8_char_len(unsigned char ch) { 222 if ((ch & 0x80) == 0) return 1; 223 switch (ch & 0xf0) { 224 case 0xf0: 225 return 4; 226 case 0xe0: 227 return 3; 228 default: 229 return 2; 230 } 231 } 232 233 /* string = '"' { quoted_printable_chars } '"' */ 234 static int json_parse_string(struct frozen *f) { 235 int n, ch = 0, len = 0; 236 TRY(json_test_and_skip(f, '"')); 237 { 238 SET_STATE(f, f->cur, "", 0); 239 for (; f->cur < f->end; f->cur += len) { 240 ch = *(unsigned char *) f->cur; 241 len = json_get_utf8_char_len((unsigned char) ch); 242 EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */ 243 EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE); 244 if (ch == '\\') { 245 EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n); 246 len += n; 247 } else if (ch == '"') { 248 json_truncate_path(f, fstate.path_len); 249 CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr); 250 f->cur++; 251 break; 252 }; 253 } 254 } 255 return ch == '"' ? 0 : JSON_STRING_INCOMPLETE; 256 } 257 258 /* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */ 259 static int json_parse_number(struct frozen *f) { 260 int ch = json_cur(f); 261 SET_STATE(f, f->cur, "", 0); 262 if (ch == '-') f->cur++; 263 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); 264 if (f->cur + 1 < f->end && f->cur[0] == '0' && f->cur[1] == 'x') { 265 f->cur += 2; 266 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); 267 EXPECT(json_isxdigit(f->cur[0]), JSON_STRING_INVALID); 268 while (f->cur < f->end && json_isxdigit(f->cur[0])) f->cur++; 269 } else { 270 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); 271 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; 272 if (f->cur < f->end && f->cur[0] == '.') { 273 f->cur++; 274 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); 275 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); 276 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; 277 } 278 if (f->cur < f->end && (f->cur[0] == 'e' || f->cur[0] == 'E')) { 279 f->cur++; 280 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); 281 if ((f->cur[0] == '+' || f->cur[0] == '-')) f->cur++; 282 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); 283 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID); 284 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++; 285 } 286 } 287 json_truncate_path(f, fstate.path_len); 288 CALL_BACK(f, JSON_TYPE_NUMBER, fstate.ptr, f->cur - fstate.ptr); 289 return 0; 290 } 291 292 #if JSON_ENABLE_ARRAY 293 /* array = '[' [ value { ',' value } ] ']' */ 294 static int json_parse_array(struct frozen *f) { 295 int i = 0, current_path_len; 296 char buf[20]; 297 CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0); 298 TRY(json_test_and_skip(f, '[')); 299 { 300 { 301 SET_STATE(f, f->cur - 1, "", 0); 302 while (json_cur(f) != ']') { 303 snprintf(buf, sizeof(buf), "[%d]", i); 304 i++; 305 current_path_len = json_append_to_path(f, buf, strlen(buf)); 306 f->cur_name = 307 f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/; 308 f->cur_name_len = strlen(buf) - 2 /*braces*/; 309 TRY(json_parse_value(f)); 310 json_truncate_path(f, current_path_len); 311 if (json_cur(f) == ',') f->cur++; 312 } 313 TRY(json_test_and_skip(f, ']')); 314 json_truncate_path(f, fstate.path_len); 315 CALL_BACK(f, JSON_TYPE_ARRAY_END, fstate.ptr, f->cur - fstate.ptr); 316 } 317 } 318 return 0; 319 } 320 #endif /* JSON_ENABLE_ARRAY */ 321 322 static int json_expect(struct frozen *f, const char *s, int len, 323 enum json_token_type tok_type) { 324 int i, n = json_left(f); 325 SET_STATE(f, f->cur, "", 0); 326 for (i = 0; i < len; i++) { 327 if (i >= n) return JSON_STRING_INCOMPLETE; 328 if (f->cur[i] != s[i]) return JSON_STRING_INVALID; 329 } 330 f->cur += len; 331 json_truncate_path(f, fstate.path_len); 332 333 CALL_BACK(f, tok_type, fstate.ptr, f->cur - fstate.ptr); 334 335 return 0; 336 } 337 338 /* value = 'null' | 'true' | 'false' | number | string | array | object */ 339 static int json_parse_value(struct frozen *f) { 340 int ch = json_cur(f); 341 342 switch (ch) { 343 case '"': 344 TRY(json_parse_string(f)); 345 break; 346 case '{': 347 TRY(json_parse_object(f)); 348 break; 349 #if JSON_ENABLE_ARRAY 350 case '[': 351 TRY(json_parse_array(f)); 352 break; 353 #endif 354 case 'n': 355 TRY(json_expect(f, "null", 4, JSON_TYPE_NULL)); 356 break; 357 case 't': 358 TRY(json_expect(f, "true", 4, JSON_TYPE_TRUE)); 359 break; 360 case 'f': 361 TRY(json_expect(f, "false", 5, JSON_TYPE_FALSE)); 362 break; 363 case '-': 364 case '0': 365 case '1': 366 case '2': 367 case '3': 368 case '4': 369 case '5': 370 case '6': 371 case '7': 372 case '8': 373 case '9': 374 TRY(json_parse_number(f)); 375 break; 376 default: 377 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; 378 } 379 380 return 0; 381 } 382 383 /* key = identifier | string */ 384 static int json_parse_key(struct frozen *f) { 385 int ch = json_cur(f); 386 if (json_isalpha(ch)) { 387 TRY(json_parse_identifier(f)); 388 } else if (ch == '"') { 389 TRY(json_parse_string(f)); 390 } else { 391 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; 392 } 393 return 0; 394 } 395 396 /* pair = key ':' value */ 397 static int json_parse_pair(struct frozen *f) { 398 int current_path_len; 399 const char *tok; 400 json_skip_whitespaces(f); 401 tok = f->cur; 402 TRY(json_parse_key(f)); 403 { 404 f->cur_name = *tok == '"' ? tok + 1 : tok; 405 f->cur_name_len = *tok == '"' ? f->cur - tok - 2 : f->cur - tok; 406 current_path_len = json_append_to_path(f, f->cur_name, f->cur_name_len); 407 } 408 TRY(json_test_and_skip(f, ':')); 409 TRY(json_parse_value(f)); 410 json_truncate_path(f, current_path_len); 411 return 0; 412 } 413 414 /* object = '{' pair { ',' pair } '}' */ 415 static int json_parse_object(struct frozen *f) { 416 CALL_BACK(f, JSON_TYPE_OBJECT_START, NULL, 0); 417 TRY(json_test_and_skip(f, '{')); 418 { 419 SET_STATE(f, f->cur - 1, ".", 1); 420 while (json_cur(f) != '}') { 421 TRY(json_parse_pair(f)); 422 if (json_cur(f) == ',') f->cur++; 423 } 424 TRY(json_test_and_skip(f, '}')); 425 json_truncate_path(f, fstate.path_len); 426 CALL_BACK(f, JSON_TYPE_OBJECT_END, fstate.ptr, f->cur - fstate.ptr); 427 } 428 return 0; 429 } 430 431 static int json_doit(struct frozen *f) { 432 if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID; 433 if (f->end == f->cur) return JSON_STRING_INCOMPLETE; 434 return json_parse_value(f); 435 } 436 437 int json_escape(struct json_out *out, const char *p, size_t len) WEAK; 438 int json_escape(struct json_out *out, const char *p, size_t len) { 439 size_t i, cl, n = 0; 440 const char *hex_digits = "0123456789abcdef"; 441 const char *specials = "btnvfr"; 442 443 for (i = 0; i < len; i++) { 444 unsigned char ch = ((unsigned char *) p)[i]; 445 if (ch == '"' || ch == '\\') { 446 n += out->printer(out, "\\", 1); 447 n += out->printer(out, p + i, 1); 448 } else if (ch >= '\b' && ch <= '\r') { 449 n += out->printer(out, "\\", 1); 450 n += out->printer(out, &specials[ch - '\b'], 1); 451 } else if (isprint(ch)) { 452 n += out->printer(out, p + i, 1); 453 } else if ((cl = json_get_utf8_char_len(ch)) == 1) { 454 n += out->printer(out, "\\u00", 4); 455 n += out->printer(out, &hex_digits[(ch >> 4) % 0xf], 1); 456 n += out->printer(out, &hex_digits[ch % 0xf], 1); 457 } else { 458 n += out->printer(out, p + i, cl); 459 i += cl - 1; 460 } 461 } 462 463 return n; 464 } 465 466 int json_printer_buf(struct json_out *out, const char *buf, size_t len) WEAK; 467 int json_printer_buf(struct json_out *out, const char *buf, size_t len) { 468 size_t avail = out->u.buf.size - out->u.buf.len; 469 size_t n = len < avail ? len : avail; 470 memcpy(out->u.buf.buf + out->u.buf.len, buf, n); 471 out->u.buf.len += n; 472 if (out->u.buf.size > 0) { 473 size_t idx = out->u.buf.len; 474 if (idx >= out->u.buf.size) idx = out->u.buf.size - 1; 475 out->u.buf.buf[idx] = '\0'; 476 } 477 return len; 478 } 479 480 int json_printer_file(struct json_out *out, const char *buf, size_t len) WEAK; 481 int json_printer_file(struct json_out *out, const char *buf, size_t len) { 482 return fwrite(buf, 1, len, out->u.fp); 483 } 484 485 #if JSON_ENABLE_BASE64 486 static int b64idx(int c) { 487 if (c < 26) { 488 return c + 'A'; 489 } else if (c < 52) { 490 return c - 26 + 'a'; 491 } else if (c < 62) { 492 return c - 52 + '0'; 493 } else { 494 return c == 62 ? '+' : '/'; 495 } 496 } 497 498 static int b64rev(int c) { 499 if (c >= 'A' && c <= 'Z') { 500 return c - 'A'; 501 } else if (c >= 'a' && c <= 'z') { 502 return c + 26 - 'a'; 503 } else if (c >= '0' && c <= '9') { 504 return c + 52 - '0'; 505 } else if (c == '+') { 506 return 62; 507 } else if (c == '/') { 508 return 63; 509 } else { 510 return 64; 511 } 512 } 513 514 static int b64enc(struct json_out *out, const unsigned char *p, int n) { 515 char buf[4]; 516 int i, len = 0; 517 for (i = 0; i < n; i += 3) { 518 int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0; 519 buf[0] = b64idx(a >> 2); 520 buf[1] = b64idx((a & 3) << 4 | (b >> 4)); 521 buf[2] = b64idx((b & 15) << 2 | (c >> 6)); 522 buf[3] = b64idx(c & 63); 523 if (i + 1 >= n) buf[2] = '='; 524 if (i + 2 >= n) buf[3] = '='; 525 len += out->printer(out, buf, sizeof(buf)); 526 } 527 return len; 528 } 529 530 static int b64dec(const char *src, int n, char *dst) { 531 const char *end = src + n; 532 int len = 0; 533 while (src + 3 < end) { 534 int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]), 535 d = b64rev(src[3]); 536 dst[len++] = (a << 2) | (b >> 4); 537 if (src[2] != '=') { 538 dst[len++] = (b << 4) | (c >> 2); 539 if (src[3] != '=') { 540 dst[len++] = (c << 6) | d; 541 } 542 } 543 src += 4; 544 } 545 return len; 546 } 547 #endif /* JSON_ENABLE_BASE64 */ 548 549 static unsigned char hexdec(const char *s) { 550 #define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W') 551 int a = tolower(*(const unsigned char *) s); 552 int b = tolower(*(const unsigned char *) (s + 1)); 553 return (HEXTOI(a) << 4) | HEXTOI(b); 554 } 555 556 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) WEAK; 557 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) { 558 int len = 0; 559 const char *quote = "\"", *null = "null"; 560 va_list ap; 561 va_copy(ap, xap); 562 563 while (*fmt != '\0') { 564 if (strchr(":, \r\n\t[]{}\"", *fmt) != NULL) { 565 len += out->printer(out, fmt, 1); 566 fmt++; 567 } else if (fmt[0] == '%') { 568 char buf[21]; 569 size_t skip = 2; 570 571 if (fmt[1] == 'l' && fmt[2] == 'l' && (fmt[3] == 'd' || fmt[3] == 'u')) { 572 int64_t val = va_arg(ap, int64_t); 573 const char *fmt2 = fmt[3] == 'u' ? "%" UINT64_FMT : "%" INT64_FMT; 574 snprintf(buf, sizeof(buf), fmt2, val); 575 len += out->printer(out, buf, strlen(buf)); 576 skip += 2; 577 } else if (fmt[1] == 'z' && fmt[2] == 'u') { 578 size_t val = va_arg(ap, size_t); 579 snprintf(buf, sizeof(buf), "%lu", (unsigned long) val); 580 len += out->printer(out, buf, strlen(buf)); 581 skip += 1; 582 } else if (fmt[1] == 'M') { 583 json_printf_callback_t f = va_arg(ap, json_printf_callback_t); 584 len += f(out, &ap); 585 } else if (fmt[1] == 'B') { 586 int val = va_arg(ap, int); 587 const char *str = val ? "true" : "false"; 588 len += out->printer(out, str, strlen(str)); 589 } else if (fmt[1] == 'H') { 590 #if JSON_ENABLE_HEX 591 const char *hex = "0123456789abcdef"; 592 int i, n = va_arg(ap, int); 593 const unsigned char *p = va_arg(ap, const unsigned char *); 594 len += out->printer(out, quote, 1); 595 for (i = 0; i < n; i++) { 596 len += out->printer(out, &hex[(p[i] >> 4) & 0xf], 1); 597 len += out->printer(out, &hex[p[i] & 0xf], 1); 598 } 599 len += out->printer(out, quote, 1); 600 #endif /* JSON_ENABLE_HEX */ 601 } else if (fmt[1] == 'V') { 602 #if JSON_ENABLE_BASE64 603 const unsigned char *p = va_arg(ap, const unsigned char *); 604 int n = va_arg(ap, int); 605 len += out->printer(out, quote, 1); 606 len += b64enc(out, p, n); 607 len += out->printer(out, quote, 1); 608 #endif /* JSON_ENABLE_BASE64 */ 609 } else if (fmt[1] == 'Q' || 610 (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) { 611 size_t l = 0; 612 const char *p; 613 614 if (fmt[1] == '.') { 615 l = (size_t) va_arg(ap, int); 616 skip += 2; 617 } 618 p = va_arg(ap, char *); 619 620 if (p == NULL) { 621 len += out->printer(out, null, 4); 622 } else { 623 if (fmt[1] == 'Q') { 624 l = strlen(p); 625 } 626 len += out->printer(out, quote, 1); 627 len += json_escape(out, p, l); 628 len += out->printer(out, quote, 1); 629 } 630 } else { 631 /* 632 * we delegate printing to the system printf. 633 * The goal here is to delegate all modifiers parsing to the system 634 * printf, as you can see below we still have to parse the format 635 * types. 636 * 637 * Currently, %s with strings longer than 20 chars will require 638 * double-buffering (an auxiliary buffer will be allocated from heap). 639 * TODO(dfrank): reimplement %s and %.*s in order to avoid that. 640 */ 641 642 const char *end_of_format_specifier = "sdfFeEgGlhuIcx.*-0123456789"; 643 int n = strspn(fmt + 1, end_of_format_specifier); 644 char *pbuf = buf; 645 int need_len, size = sizeof(buf); 646 char fmt2[20]; 647 va_list ap_copy; 648 strncpy(fmt2, fmt, 649 n + 1 > (int) sizeof(fmt2) ? sizeof(fmt2) : (size_t) n + 1); 650 fmt2[n + 1] = '\0'; 651 652 va_copy(ap_copy, ap); 653 need_len = vsnprintf(pbuf, size, fmt2, ap_copy); 654 va_end(ap_copy); 655 656 if (need_len < 0) { 657 /* 658 * Windows & eCos vsnprintf implementation return -1 on overflow 659 * instead of needed size. 660 */ 661 pbuf = NULL; 662 while (need_len < 0) { 663 free(pbuf); 664 size *= 2; 665 if ((pbuf = (char *) malloc(size)) == NULL) break; 666 va_copy(ap_copy, ap); 667 need_len = vsnprintf(pbuf, size, fmt2, ap_copy); 668 va_end(ap_copy); 669 } 670 } else if (need_len >= (int) sizeof(buf)) { 671 /* 672 * resulting string doesn't fit into a stack-allocated buffer `buf`, 673 * so we need to allocate a new buffer from heap and use it 674 */ 675 if ((pbuf = (char *) malloc(need_len + 1)) != NULL) { 676 va_copy(ap_copy, ap); 677 vsnprintf(pbuf, need_len + 1, fmt2, ap_copy); 678 va_end(ap_copy); 679 } 680 } 681 if (pbuf == NULL) { 682 buf[0] = '\0'; 683 pbuf = buf; 684 } 685 686 /* 687 * however we need to parse the type ourselves in order to advance 688 * the va_list by the correct amount; there is no portable way to 689 * inherit the advancement made by vprintf. 690 * 32-bit (linux or windows) passes va_list by value. 691 */ 692 if ((n + 1 == (int) strlen("%" PRId64) && 693 strcmp(fmt2, "%" PRId64) == 0) || 694 (n + 1 == (int) strlen("%" PRIu64) && 695 strcmp(fmt2, "%" PRIu64) == 0)) { 696 (void) va_arg(ap, int64_t); 697 } else if (strcmp(fmt2, "%.*s") == 0) { 698 (void) va_arg(ap, int); 699 (void) va_arg(ap, char *); 700 } else { 701 switch (fmt2[n]) { 702 case 'u': 703 case 'd': 704 (void) va_arg(ap, int); 705 break; 706 case 'g': 707 case 'f': 708 (void) va_arg(ap, double); 709 break; 710 case 'p': 711 (void) va_arg(ap, void *); 712 break; 713 default: 714 /* many types are promoted to int */ 715 (void) va_arg(ap, int); 716 } 717 } 718 719 len += out->printer(out, pbuf, strlen(pbuf)); 720 skip = n + 1; 721 722 /* If buffer was allocated from heap, free it */ 723 if (pbuf != buf) { 724 free(pbuf); 725 pbuf = NULL; 726 } 727 } 728 fmt += skip; 729 } else if (*fmt == '_' || json_isalpha(*fmt)) { 730 len += out->printer(out, quote, 1); 731 while (*fmt == '_' || json_isalpha(*fmt) || json_isdigit(*fmt)) { 732 len += out->printer(out, fmt, 1); 733 fmt++; 734 } 735 len += out->printer(out, quote, 1); 736 } else { 737 len += out->printer(out, fmt, 1); 738 fmt++; 739 } 740 } 741 va_end(ap); 742 743 return len; 744 } 745 746 int json_printf(struct json_out *out, const char *fmt, ...) WEAK; 747 int json_printf(struct json_out *out, const char *fmt, ...) { 748 int n; 749 va_list ap; 750 va_start(ap, fmt); 751 n = json_vprintf(out, fmt, ap); 752 va_end(ap); 753 return n; 754 } 755 756 int json_printf_array(struct json_out *out, va_list *ap) WEAK; 757 int json_printf_array(struct json_out *out, va_list *ap) { 758 int len = 0; 759 char *arr = va_arg(*ap, char *); 760 size_t i, arr_size = va_arg(*ap, size_t); 761 size_t elem_size = va_arg(*ap, size_t); 762 const char *fmt = va_arg(*ap, char *); 763 len += json_printf(out, "[", 1); 764 for (i = 0; arr != NULL && i < arr_size / elem_size; i++) { 765 union { 766 int64_t i; 767 double d; 768 } val; 769 memcpy(&val, arr + i * elem_size, 770 elem_size > sizeof(val) ? sizeof(val) : elem_size); 771 if (i > 0) len += json_printf(out, ", "); 772 if (strpbrk(fmt, "efg") != NULL) { 773 len += json_printf(out, fmt, val.d); 774 } else { 775 len += json_printf(out, fmt, val.i); 776 } 777 } 778 len += json_printf(out, "]", 1); 779 return len; 780 } 781 782 #ifdef _WIN32 783 int cs_win_vsnprintf(char *str, size_t size, const char *format, 784 va_list ap) WEAK; 785 int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap) { 786 int res = _vsnprintf(str, size, format, ap); 787 va_end(ap); 788 if (res >= size) { 789 str[size - 1] = '\0'; 790 } 791 return res; 792 } 793 794 int cs_win_snprintf(char *str, size_t size, const char *format, ...) WEAK; 795 int cs_win_snprintf(char *str, size_t size, const char *format, ...) { 796 int res; 797 va_list ap; 798 va_start(ap, format); 799 res = vsnprintf(str, size, format, ap); 800 va_end(ap); 801 return res; 802 } 803 #endif /* _WIN32 */ 804 805 int json_walk(const char *json_string, int json_string_length, 806 json_walk_callback_t callback, void *callback_data) WEAK; 807 int json_walk(const char *json_string, int json_string_length, 808 json_walk_callback_t callback, void *callback_data) { 809 struct frozen frozen; 810 811 memset(&frozen, 0, sizeof(frozen)); 812 frozen.end = json_string + json_string_length; 813 frozen.cur = json_string; 814 frozen.callback_data = callback_data; 815 frozen.callback = callback; 816 817 TRY(json_doit(&frozen)); 818 819 return frozen.cur - json_string; 820 } 821 822 struct scan_array_info { 823 int found; 824 char path[JSON_MAX_PATH_LEN]; 825 struct json_token *token; 826 }; 827 828 static void json_scanf_array_elem_cb(void *callback_data, const char *name, 829 size_t name_len, const char *path, 830 const struct json_token *token) { 831 struct scan_array_info *info = (struct scan_array_info *) callback_data; 832 833 (void) name; 834 (void) name_len; 835 836 if (strcmp(path, info->path) == 0) { 837 *info->token = *token; 838 info->found = 1; 839 } 840 } 841 842 int json_scanf_array_elem(const char *s, int len, const char *path, int idx, 843 struct json_token *token) WEAK; 844 int json_scanf_array_elem(const char *s, int len, const char *path, int idx, 845 struct json_token *token) { 846 struct scan_array_info info; 847 info.token = token; 848 info.found = 0; 849 memset(token, 0, sizeof(*token)); 850 snprintf(info.path, sizeof(info.path), "%s[%d]", path, idx); 851 json_walk(s, len, json_scanf_array_elem_cb, &info); 852 return info.found ? token->len : -1; 853 } 854 855 struct json_scanf_info { 856 int num_conversions; 857 char *path; 858 const char *fmt; 859 void *target; 860 void *user_data; 861 int type; 862 }; 863 864 int json_unescape(const char *src, int slen, char *dst, int dlen) WEAK; 865 int json_unescape(const char *src, int slen, char *dst, int dlen) { 866 char *send = (char *) src + slen, *dend = dst + dlen, *orig_dst = dst, *p; 867 const char *esc1 = "\"\\/bfnrt", *esc2 = "\"\\/\b\f\n\r\t"; 868 869 while (src < send) { 870 if (*src == '\\') { 871 if (++src >= send) return JSON_STRING_INCOMPLETE; 872 if (*src == 'u') { 873 if (send - src < 5) return JSON_STRING_INCOMPLETE; 874 /* Here we go: this is a \u.... escape. Process simple one-byte chars */ 875 if (src[1] == '0' && src[2] == '0') { 876 /* This is \u00xx character from the ASCII range */ 877 if (dst < dend) *dst = hexdec(src + 3); 878 src += 4; 879 } else { 880 /* Complex \uXXXX escapes drag utf8 lib... Do it at some stage */ 881 return JSON_STRING_INVALID; 882 } 883 } else if ((p = (char *) strchr(esc1, *src)) != NULL) { 884 if (dst < dend) *dst = esc2[p - esc1]; 885 } else { 886 return JSON_STRING_INVALID; 887 } 888 } else { 889 if (dst < dend) *dst = *src; 890 } 891 dst++; 892 src++; 893 } 894 895 return dst - orig_dst; 896 } 897 898 static void json_scanf_cb(void *callback_data, const char *name, 899 size_t name_len, const char *path, 900 const struct json_token *token) { 901 struct json_scanf_info *info = (struct json_scanf_info *) callback_data; 902 char buf[32]; /* Must be enough to hold numbers */ 903 904 (void) name; 905 (void) name_len; 906 907 if (token->ptr == NULL) { 908 /* 909 * We're not interested here in the events for which we have no value; 910 * namely, JSON_TYPE_OBJECT_START and JSON_TYPE_ARRAY_START 911 */ 912 return; 913 } 914 915 if (strcmp(path, info->path) != 0) { 916 /* It's not the path we're looking for, so, just ignore this callback */ 917 return; 918 } 919 920 switch (info->type) { 921 case 'B': 922 info->num_conversions++; 923 switch (sizeof(bool)) { 924 case sizeof(char): 925 *(char *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0); 926 break; 927 case sizeof(int): 928 *(int *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0); 929 break; 930 default: 931 /* should never be here */ 932 abort(); 933 } 934 break; 935 case 'M': { 936 union { 937 void *p; 938 json_scanner_t f; 939 } u = {info->target}; 940 info->num_conversions++; 941 u.f(token->ptr, token->len, info->user_data); 942 break; 943 } 944 case 'Q': { 945 char **dst = (char **) info->target; 946 if (token->type == JSON_TYPE_NULL) { 947 *dst = NULL; 948 } else { 949 int unescaped_len = json_unescape(token->ptr, token->len, NULL, 0); 950 if (unescaped_len >= 0 && 951 (*dst = (char *) malloc(unescaped_len + 1)) != NULL) { 952 info->num_conversions++; 953 if (json_unescape(token->ptr, token->len, *dst, unescaped_len) == 954 unescaped_len) { 955 (*dst)[unescaped_len] = '\0'; 956 } else { 957 free(*dst); 958 *dst = NULL; 959 } 960 } 961 } 962 break; 963 } 964 case 'H': { 965 #if JSON_ENABLE_HEX 966 char **dst = (char **) info->user_data; 967 int i, len = token->len / 2; 968 *(int *) info->target = len; 969 if ((*dst = (char *) malloc(len + 1)) != NULL) { 970 for (i = 0; i < len; i++) { 971 (*dst)[i] = hexdec(token->ptr + 2 * i); 972 } 973 (*dst)[len] = '\0'; 974 info->num_conversions++; 975 } 976 #endif /* JSON_ENABLE_HEX */ 977 break; 978 } 979 case 'V': { 980 #if JSON_ENABLE_BASE64 981 char **dst = (char **) info->target; 982 int len = token->len * 4 / 3 + 2; 983 if ((*dst = (char *) malloc(len + 1)) != NULL) { 984 int n = b64dec(token->ptr, token->len, *dst); 985 (*dst)[n] = '\0'; 986 *(int *) info->user_data = n; 987 info->num_conversions++; 988 } 989 #endif /* JSON_ENABLE_BASE64 */ 990 break; 991 } 992 case 'T': 993 info->num_conversions++; 994 *(struct json_token *) info->target = *token; 995 break; 996 default: 997 if (token->len >= (int) sizeof(buf)) break; 998 /* Before converting, copy into tmp buffer in order to 0-terminate it */ 999 memcpy(buf, token->ptr, token->len); 1000 buf[token->len] = '\0'; 1001 /* NB: Use of base 0 for %d, %ld, %u and %lu is intentional. */ 1002 if (info->fmt[1] == 'd' || (info->fmt[1] == 'l' && info->fmt[2] == 'd') || 1003 info->fmt[1] == 'i') { 1004 char *endptr = NULL; 1005 long r = strtol(buf, &endptr, 0 /* base */); 1006 if (*endptr == '\0') { 1007 if (info->fmt[1] == 'l') { 1008 *((long *) info->target) = r; 1009 } else { 1010 *((int *) info->target) = (int) r; 1011 } 1012 info->num_conversions++; 1013 } 1014 } else if (info->fmt[1] == 'u' || 1015 (info->fmt[1] == 'l' && info->fmt[2] == 'u')) { 1016 char *endptr = NULL; 1017 unsigned long r = strtoul(buf, &endptr, 0 /* base */); 1018 if (*endptr == '\0') { 1019 if (info->fmt[1] == 'l') { 1020 *((unsigned long *) info->target) = r; 1021 } else { 1022 *((unsigned int *) info->target) = (unsigned int) r; 1023 } 1024 info->num_conversions++; 1025 } 1026 } else { 1027 #if !JSON_MINIMAL 1028 info->num_conversions += sscanf(buf, info->fmt, info->target); 1029 #endif 1030 } 1031 break; 1032 } 1033 } 1034 1035 int json_vscanf(const char *s, int len, const char *fmt, va_list ap) WEAK; 1036 int json_vscanf(const char *s, int len, const char *fmt, va_list ap) { 1037 char path[JSON_MAX_PATH_LEN] = "", fmtbuf[20]; 1038 int i = 0; 1039 char *p = NULL; 1040 struct json_scanf_info info = {0, path, fmtbuf, NULL, NULL, 0}; 1041 1042 while (fmt[i] != '\0') { 1043 if (fmt[i] == '{') { 1044 strcat(path, "."); 1045 i++; 1046 } else if (fmt[i] == '}') { 1047 if ((p = strrchr(path, '.')) != NULL) *p = '\0'; 1048 i++; 1049 } else if (fmt[i] == '%') { 1050 info.target = va_arg(ap, void *); 1051 info.type = fmt[i + 1]; 1052 switch (fmt[i + 1]) { 1053 case 'M': 1054 case 'V': 1055 case 'H': 1056 info.user_data = va_arg(ap, void *); 1057 /* FALLTHROUGH */ 1058 case 'B': 1059 case 'Q': 1060 case 'T': 1061 i += 2; 1062 break; 1063 default: { 1064 const char *delims = ", \t\r\n]}"; 1065 int conv_len = strcspn(fmt + i + 1, delims) + 1; 1066 memcpy(fmtbuf, fmt + i, conv_len); 1067 fmtbuf[conv_len] = '\0'; 1068 i += conv_len; 1069 i += strspn(fmt + i, delims); 1070 break; 1071 } 1072 } 1073 json_walk(s, len, json_scanf_cb, &info); 1074 } else if (json_isalpha(fmt[i]) || json_get_utf8_char_len(fmt[i]) > 1) { 1075 char *pe; 1076 const char *delims = ": \r\n\t"; 1077 int key_len = strcspn(&fmt[i], delims); 1078 if ((p = strrchr(path, '.')) != NULL) p[1] = '\0'; 1079 pe = path + strlen(path); 1080 memcpy(pe, fmt + i, key_len); 1081 pe[key_len] = '\0'; 1082 i += key_len + strspn(fmt + i + key_len, delims); 1083 } else { 1084 i++; 1085 } 1086 } 1087 return info.num_conversions; 1088 } 1089 1090 int json_scanf(const char *str, int len, const char *fmt, ...) WEAK; 1091 int json_scanf(const char *str, int len, const char *fmt, ...) { 1092 int result; 1093 va_list ap; 1094 va_start(ap, fmt); 1095 result = json_vscanf(str, len, fmt, ap); 1096 va_end(ap); 1097 return result; 1098 } 1099 1100 int json_vfprintf(const char *file_name, const char *fmt, va_list ap) WEAK; 1101 int json_vfprintf(const char *file_name, const char *fmt, va_list ap) { 1102 int res = -1; 1103 FILE *fp = fopen(file_name, "wb"); 1104 if (fp != NULL) { 1105 struct json_out out = JSON_OUT_FILE(fp); 1106 res = json_vprintf(&out, fmt, ap); 1107 fputc('\n', fp); 1108 fclose(fp); 1109 } 1110 return res; 1111 } 1112 1113 int json_fprintf(const char *file_name, const char *fmt, ...) WEAK; 1114 int json_fprintf(const char *file_name, const char *fmt, ...) { 1115 int result; 1116 va_list ap; 1117 va_start(ap, fmt); 1118 result = json_vfprintf(file_name, fmt, ap); 1119 va_end(ap); 1120 return result; 1121 } 1122 1123 char *json_fread(const char *path) WEAK; 1124 char *json_fread(const char *path) { 1125 FILE *fp; 1126 char *data = NULL; 1127 if ((fp = fopen(path, "rb")) == NULL) { 1128 } else if (fseek(fp, 0, SEEK_END) != 0) { 1129 fclose(fp); 1130 } else { 1131 long size = ftell(fp); 1132 if (size > 0 && (data = (char *) malloc(size + 1)) != NULL) { 1133 fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */ 1134 if (fread(data, 1, size, fp) != (size_t) size) { 1135 free(data); 1136 data = NULL; 1137 } else { 1138 data[size] = '\0'; 1139 } 1140 } 1141 fclose(fp); 1142 } 1143 return data; 1144 } 1145 1146 struct json_setf_data { 1147 const char *json_path; 1148 const char *base; /* Pointer to the source JSON string */ 1149 int matched; /* Matched part of json_path */ 1150 int pos; /* Offset of the mutated value begin */ 1151 int end; /* Offset of the mutated value end */ 1152 int prev; /* Offset of the previous token end */ 1153 }; 1154 1155 static int get_matched_prefix_len(const char *s1, const char *s2) { 1156 int i = 0; 1157 while (s1[i] && s2[i] && s1[i] == s2[i]) i++; 1158 return i; 1159 } 1160 1161 static void json_vsetf_cb(void *userdata, const char *name, size_t name_len, 1162 const char *path, const struct json_token *t) { 1163 struct json_setf_data *data = (struct json_setf_data *) userdata; 1164 int off, len = get_matched_prefix_len(path, data->json_path); 1165 if (t->ptr == NULL) return; 1166 off = t->ptr - data->base; 1167 if (len > data->matched) data->matched = len; 1168 1169 /* 1170 * If there is no exact path match, set the mutation position to tbe end 1171 * of the object or array 1172 */ 1173 if (len < data->matched && data->pos == 0 && 1174 (t->type == JSON_TYPE_OBJECT_END || t->type == JSON_TYPE_ARRAY_END)) { 1175 data->pos = data->end = data->prev; 1176 } 1177 1178 /* Exact path match. Set mutation position to the value of this token */ 1179 if (strcmp(path, data->json_path) == 0 && t->type != JSON_TYPE_OBJECT_START && 1180 t->type != JSON_TYPE_ARRAY_START) { 1181 data->pos = off; 1182 data->end = off + t->len; 1183 } 1184 1185 /* 1186 * For deletion, we need to know where the previous value ends, because 1187 * we don't know where matched value key starts. 1188 * When the mutation position is not yet set, remember each value end. 1189 * When the mutation position is already set, but it is at the beginning 1190 * of the object/array, we catch the end of the object/array and see 1191 * whether the object/array start is closer then previously stored prev. 1192 */ 1193 if (data->pos == 0) { 1194 data->prev = off + t->len; /* pos is not yet set */ 1195 } else if ((t->ptr[0] == '[' || t->ptr[0] == '{') && off + 1 < data->pos && 1196 off + 1 > data->prev) { 1197 data->prev = off + 1; 1198 } 1199 (void) name; 1200 (void) name_len; 1201 } 1202 1203 int json_vsetf(const char *s, int len, struct json_out *out, 1204 const char *json_path, const char *json_fmt, va_list ap) WEAK; 1205 int json_vsetf(const char *s, int len, struct json_out *out, 1206 const char *json_path, const char *json_fmt, va_list ap) { 1207 struct json_setf_data data; 1208 memset(&data, 0, sizeof(data)); 1209 data.json_path = json_path; 1210 data.base = s; 1211 data.end = len; 1212 json_walk(s, len, json_vsetf_cb, &data); 1213 if (json_fmt == NULL) { 1214 /* Deletion codepath */ 1215 json_printf(out, "%.*s", data.prev, s); 1216 /* Trim comma after the value that begins at object/array start */ 1217 if (s[data.prev - 1] == '{' || s[data.prev - 1] == '[') { 1218 int i = data.end; 1219 while (i < len && json_isspace(s[i])) i++; 1220 if (s[i] == ',') data.end = i + 1; /* Point after comma */ 1221 } 1222 json_printf(out, "%.*s", len - data.end, s + data.end); 1223 } else { 1224 /* Modification codepath */ 1225 int n, off = data.matched, depth = 0; 1226 1227 /* Print the unchanged beginning */ 1228 json_printf(out, "%.*s", data.pos, s); 1229 1230 /* Add missing keys */ 1231 while ((n = strcspn(&json_path[off], ".[")) > 0) { 1232 if (s[data.prev - 1] != '{' && s[data.prev - 1] != '[' && depth == 0) { 1233 json_printf(out, ","); 1234 } 1235 if (off > 0 && json_path[off - 1] != '.') break; 1236 json_printf(out, "%.*Q:", n, json_path + off); 1237 off += n; 1238 if (json_path[off] != '\0') { 1239 json_printf(out, "%c", json_path[off] == '.' ? '{' : '['); 1240 depth++; 1241 off++; 1242 } 1243 } 1244 /* Print the new value */ 1245 json_vprintf(out, json_fmt, ap); 1246 1247 /* Close brackets/braces of the added missing keys */ 1248 for (; off > data.matched; off--) { 1249 int ch = json_path[off]; 1250 const char *p = ch == '.' ? "}" : ch == '[' ? "]" : ""; 1251 json_printf(out, "%s", p); 1252 } 1253 1254 /* Print the rest of the unchanged string */ 1255 json_printf(out, "%.*s", len - data.end, s + data.end); 1256 } 1257 return data.end > data.pos ? 1 : 0; 1258 } 1259 1260 int json_setf(const char *s, int len, struct json_out *out, 1261 const char *json_path, const char *json_fmt, ...) WEAK; 1262 int json_setf(const char *s, int len, struct json_out *out, 1263 const char *json_path, const char *json_fmt, ...) { 1264 int result; 1265 va_list ap; 1266 va_start(ap, json_fmt); 1267 result = json_vsetf(s, len, out, json_path, json_fmt, ap); 1268 va_end(ap); 1269 return result; 1270 } 1271 1272 struct prettify_data { 1273 struct json_out *out; 1274 int level; 1275 int last_token; 1276 }; 1277 1278 static void indent(struct json_out *out, int level) { 1279 while (level-- > 0) out->printer(out, " ", 2); 1280 } 1281 1282 static void print_key(struct prettify_data *pd, const char *path, 1283 const char *name, int name_len) { 1284 if (pd->last_token != JSON_TYPE_INVALID && 1285 pd->last_token != JSON_TYPE_ARRAY_START && 1286 pd->last_token != JSON_TYPE_OBJECT_START) { 1287 pd->out->printer(pd->out, ",", 1); 1288 } 1289 if (path[0] != '\0') pd->out->printer(pd->out, "\n", 1); 1290 indent(pd->out, pd->level); 1291 if (path[0] != '\0' && path[strlen(path) - 1] != ']') { 1292 pd->out->printer(pd->out, "\"", 1); 1293 pd->out->printer(pd->out, name, (int) name_len); 1294 pd->out->printer(pd->out, "\"", 1); 1295 pd->out->printer(pd->out, ": ", 2); 1296 } 1297 } 1298 1299 static void prettify_cb(void *userdata, const char *name, size_t name_len, 1300 const char *path, const struct json_token *t) { 1301 struct prettify_data *pd = (struct prettify_data *) userdata; 1302 switch (t->type) { 1303 case JSON_TYPE_OBJECT_START: 1304 case JSON_TYPE_ARRAY_START: 1305 print_key(pd, path, name, name_len); 1306 pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_START ? "[" : "{", 1307 1); 1308 pd->level++; 1309 break; 1310 case JSON_TYPE_OBJECT_END: 1311 case JSON_TYPE_ARRAY_END: 1312 pd->level--; 1313 if (pd->last_token != JSON_TYPE_INVALID && 1314 pd->last_token != JSON_TYPE_ARRAY_START && 1315 pd->last_token != JSON_TYPE_OBJECT_START) { 1316 pd->out->printer(pd->out, "\n", 1); 1317 indent(pd->out, pd->level); 1318 } 1319 pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_END ? "]" : "}", 1); 1320 break; 1321 case JSON_TYPE_NUMBER: 1322 case JSON_TYPE_NULL: 1323 case JSON_TYPE_TRUE: 1324 case JSON_TYPE_FALSE: 1325 case JSON_TYPE_STRING: 1326 print_key(pd, path, name, name_len); 1327 if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1); 1328 pd->out->printer(pd->out, t->ptr, t->len); 1329 if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1); 1330 break; 1331 default: 1332 break; 1333 } 1334 pd->last_token = t->type; 1335 } 1336 1337 int json_prettify(const char *s, int len, struct json_out *out) WEAK; 1338 int json_prettify(const char *s, int len, struct json_out *out) { 1339 struct prettify_data pd = {out, 0, JSON_TYPE_INVALID}; 1340 return json_walk(s, len, prettify_cb, &pd); 1341 } 1342 1343 int json_prettify_file(const char *file_name) WEAK; 1344 int json_prettify_file(const char *file_name) { 1345 int res = -1; 1346 char *s = json_fread(file_name); 1347 FILE *fp; 1348 if (s != NULL && (fp = fopen(file_name, "wb")) != NULL) { 1349 struct json_out out = JSON_OUT_FILE(fp); 1350 res = json_prettify(s, strlen(s), &out); 1351 if (res < 0) { 1352 /* On error, restore the old content */ 1353 fclose(fp); 1354 fp = fopen(file_name, "wb"); 1355 fseek(fp, 0, SEEK_SET); 1356 fwrite(s, 1, strlen(s), fp); 1357 } else { 1358 fputc('\n', fp); 1359 } 1360 fclose(fp); 1361 } 1362 free(s); 1363 return res; 1364 } 1365 1366 struct next_data { 1367 void *handle; // Passed handle. Changed if a next entry is found 1368 const char *path; // Path to the iterated object/array 1369 int path_len; // Path length - optimisation 1370 int found; // Non-0 if found the next entry 1371 struct json_token *key; // Object's key 1372 struct json_token *val; // Object's value 1373 int *idx; // Array index 1374 }; 1375 1376 static void next_set_key(struct next_data *d, const char *name, int name_len, 1377 int is_array) { 1378 if (is_array) { 1379 /* Array. Set index and reset key */ 1380 if (d->key != NULL) { 1381 d->key->len = 0; 1382 d->key->ptr = NULL; 1383 } 1384 if (d->idx != NULL) *d->idx = atoi(name); 1385 } else { 1386 /* Object. Set key and make index -1 */ 1387 if (d->key != NULL) { 1388 d->key->ptr = name; 1389 d->key->len = name_len; 1390 } 1391 if (d->idx != NULL) *d->idx = -1; 1392 } 1393 } 1394 1395 static void json_next_cb(void *userdata, const char *name, size_t name_len, 1396 const char *path, const struct json_token *t) { 1397 struct next_data *d = (struct next_data *) userdata; 1398 const char *p = path + d->path_len; 1399 if (d->found) return; 1400 if (d->path_len >= (int) strlen(path)) return; 1401 if (strncmp(d->path, path, d->path_len) != 0) return; 1402 if (strchr(p + 1, '.') != NULL) return; /* More nested objects - skip */ 1403 if (strchr(p + 1, '[') != NULL) return; /* Ditto for arrays */ 1404 // {OBJECT,ARRAY}_END types do not pass name, _START does. Save key. 1405 if (t->type == JSON_TYPE_OBJECT_START || t->type == JSON_TYPE_ARRAY_START) { 1406 next_set_key(d, name, name_len, p[0] == '['); 1407 } else if (d->handle == NULL || d->handle < (void *) t->ptr) { 1408 if (t->type != JSON_TYPE_OBJECT_END && t->type != JSON_TYPE_ARRAY_END) { 1409 next_set_key(d, name, name_len, p[0] == '['); 1410 } 1411 if (d->val != NULL) *d->val = *t; 1412 d->handle = (void *) t->ptr; 1413 d->found = 1; 1414 } 1415 } 1416 1417 static void *json_next(const char *s, int len, void *handle, const char *path, 1418 struct json_token *key, struct json_token *val, int *i) { 1419 struct json_token tmpval, *v = val == NULL ? &tmpval : val; 1420 struct json_token tmpkey, *k = key == NULL ? &tmpkey : key; 1421 int tmpidx, *pidx = i == NULL ? &tmpidx : i; 1422 struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx}; 1423 json_walk(s, len, json_next_cb, &data); 1424 return data.found ? data.handle : NULL; 1425 } 1426 1427 void *json_next_key(const char *s, int len, void *handle, const char *path, 1428 struct json_token *key, struct json_token *val) WEAK; 1429 void *json_next_key(const char *s, int len, void *handle, const char *path, 1430 struct json_token *key, struct json_token *val) { 1431 return json_next(s, len, handle, path, key, val, NULL); 1432 } 1433 1434 void *json_next_elem(const char *s, int len, void *handle, const char *path, 1435 int *idx, struct json_token *val) WEAK; 1436 void *json_next_elem(const char *s, int len, void *handle, const char *path, 1437 int *idx, struct json_token *val) { 1438 return json_next(s, len, handle, path, NULL, val, idx); 1439 } 1440 1441 static int json_sprinter(struct json_out *out, const char *str, size_t len) { 1442 size_t old_len = out->u.buf.buf == NULL ? 0 : strlen(out->u.buf.buf); 1443 size_t new_len = len + old_len; 1444 char *p = (char *) realloc(out->u.buf.buf, new_len + 1); 1445 if (p != NULL) { 1446 memcpy(p + old_len, str, len); 1447 p[new_len] = '\0'; 1448 out->u.buf.buf = p; 1449 } 1450 return len; 1451 } 1452 1453 char *json_vasprintf(const char *fmt, va_list ap) WEAK; 1454 char *json_vasprintf(const char *fmt, va_list ap) { 1455 struct json_out out; 1456 memset(&out, 0, sizeof(out)); 1457 out.printer = json_sprinter; 1458 json_vprintf(&out, fmt, ap); 1459 return out.u.buf.buf; 1460 } 1461 1462 char *json_asprintf(const char *fmt, ...) WEAK; 1463 char *json_asprintf(const char *fmt, ...) { 1464 char *result = NULL; 1465 va_list ap; 1466 va_start(ap, fmt); 1467 result = json_vasprintf(fmt, ap); 1468 va_end(ap); 1469 return result; 1470 }