gst

painless gist creator
git clone git://edryd.org/gst
Log | Files | Refs | LICENSE

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 }