fix coverity CID 349303
[RRG-proxmark3.git] / armsrc / frozen.c
blobb8a6f3a023be13f4db5f819df1c4a63fe650ca1e
1 /*
2 * Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
3 * Copyright (c) 2018 Cesanta Software Limited
4 * All rights reserved
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */
21 #include "frozen.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include "nprintf.h"
27 #include "BigBuf.h"
28 #define malloc(X) BigBuf_malloc(X)
29 #define free(X)
31 #if !defined(WEAK)
32 #if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
33 #define WEAK __attribute__((weak))
34 #else
35 #define WEAK
36 #endif
37 #endif
39 #ifdef _WIN32
40 #undef snprintf
41 #undef vsnprintf
42 #define snprintf cs_win_snprintf
43 #define vsnprintf cs_win_vsnprintf
44 int cs_win_snprintf(char *str, size_t size, const char *format, ...);
45 int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap);
46 #if _MSC_VER >= 1700
47 #include "stdint.h"
48 #else
49 typedef _int64 int64_t;
50 typedef unsigned _int64 uint64_t;
51 #endif
52 #define PRId64 "I64d"
53 #define PRIu64 "I64u"
54 #else /* _WIN32 */
55 /* <inttypes.h> wants this for C++ */
56 #ifndef __STDC_FORMAT_MACROS
57 #define __STDC_FORMAT_MACROS
58 #endif
59 #include <inttypes.h>
60 #endif /* _WIN32 */
62 #ifndef INT64_FMT
63 #define INT64_FMT PRId64
64 #endif
65 #ifndef UINT64_FMT
66 #define UINT64_FMT PRIu64
67 #endif
69 #ifndef va_copy
70 #define va_copy(x, y) x = y
71 #endif
73 #ifndef JSON_ENABLE_ARRAY
74 #define JSON_ENABLE_ARRAY 1
75 #endif
77 struct frozen {
78 const char *end;
79 const char *cur;
81 const char *cur_name;
82 size_t cur_name_len;
84 /* For callback API */
85 char path[JSON_MAX_PATH_LEN];
86 size_t path_len;
87 void *callback_data;
88 json_walk_callback_t callback;
91 struct fstate {
92 const char *ptr;
93 size_t path_len;
96 #define SET_STATE(fr, ptr, str, len) \
97 struct fstate fstate = {(ptr), (fr)->path_len}; \
98 json_append_to_path((fr), (str), (len));
100 #define CALL_BACK(fr, tok, value, len) \
101 do { \
102 if ((fr)->callback && \
103 ((fr)->path_len == 0 || (fr)->path[(fr)->path_len - 1] != '.')) { \
104 struct json_token t = {(value), (int) (len), (tok)}; \
106 /* Call the callback with the given value and current name */ \
107 (fr)->callback((fr)->callback_data, (fr)->cur_name, (fr)->cur_name_len, \
108 (fr)->path, &t); \
110 /* Reset the name */ \
111 (fr)->cur_name = NULL; \
112 (fr)->cur_name_len = 0; \
114 } while (0)
116 static int json_append_to_path(struct frozen *f, const char *str, int size) {
117 int n = f->path_len;
118 int left = sizeof(f->path) - n - 1;
119 if (size > left) size = left;
120 memcpy(f->path + n, str, size);
121 f->path[n + size] = '\0';
122 f->path_len += size;
123 return n;
126 static void json_truncate_path(struct frozen *f, size_t len) {
127 f->path_len = len;
128 f->path[len] = '\0';
131 static int json_parse_object(struct frozen *f);
132 static int json_parse_value(struct frozen *f);
134 #define EXPECT(cond, err_code) \
135 do { \
136 if (!(cond)) return (err_code); \
137 } while (0)
139 #define TRY(expr) \
140 do { \
141 int _n = expr; \
142 if (_n < 0) return _n; \
143 } while (0)
145 #define END_OF_STRING (-1)
147 static int json_left(const struct frozen *f) {
148 return f->end - f->cur;
151 static int json_isspace(int ch) {
152 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
155 static void json_skip_whitespaces(struct frozen *f) {
156 while (f->cur < f->end && json_isspace(*f->cur)) f->cur++;
159 static int json_cur(struct frozen *f) {
160 json_skip_whitespaces(f);
161 return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur;
164 static int json_test_and_skip(struct frozen *f, int expected) {
165 int ch = json_cur(f);
166 if (ch == expected) {
167 f->cur++;
168 return 0;
170 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
173 static int json_isalpha(int ch) {
174 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
177 static int json_isdigit(int ch) {
178 return ch >= '0' && ch <= '9';
181 static int json_isxdigit(int ch) {
182 return json_isdigit(ch) || (ch >= 'a' && ch <= 'f') ||
183 (ch >= 'A' && ch <= 'F');
186 static int json_get_escape_len(const char *s, int len) {
187 switch (*s) {
188 case 'u':
189 return len < 6 ? JSON_STRING_INCOMPLETE
190 : json_isxdigit(s[1]) && json_isxdigit(s[2]) &&
191 json_isxdigit(s[3]) && json_isxdigit(s[4])
193 : JSON_STRING_INVALID;
194 case '"':
195 case '\\':
196 case '/':
197 case 'b':
198 case 'f':
199 case 'n':
200 case 'r':
201 case 't':
202 return len < 2 ? JSON_STRING_INCOMPLETE : 1;
203 default:
204 return JSON_STRING_INVALID;
208 /* identifier = letter { letter | digit | '_' } */
209 static int json_parse_identifier(struct frozen *f) {
210 EXPECT(json_isalpha(json_cur(f)), JSON_STRING_INVALID);
212 SET_STATE(f, f->cur, "", 0);
213 while (f->cur < f->end &&
214 (*f->cur == '_' || json_isalpha(*f->cur) || json_isdigit(*f->cur))) {
215 f->cur++;
217 json_truncate_path(f, fstate.path_len);
218 CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr);
220 return 0;
223 static int json_get_utf8_char_len(unsigned char ch) {
224 if ((ch & 0x80) == 0) return 1;
225 switch (ch & 0xf0) {
226 case 0xf0:
227 return 4;
228 case 0xe0:
229 return 3;
230 default:
231 return 2;
235 /* string = '"' { quoted_printable_chars } '"' */
236 static int json_parse_string(struct frozen *f) {
237 int n, ch = 0, len = 0;
238 TRY(json_test_and_skip(f, '"'));
240 SET_STATE(f, f->cur, "", 0);
241 for (; f->cur < f->end; f->cur += len) {
242 ch = *(unsigned char *) f->cur;
243 len = json_get_utf8_char_len((unsigned char) ch);
244 EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */
245 EXPECT(len <= json_left(f), JSON_STRING_INCOMPLETE);
246 if (ch == '\\') {
247 EXPECT((n = json_get_escape_len(f->cur + 1, json_left(f))) > 0, n);
248 len += n;
249 } else if (ch == '"') {
250 json_truncate_path(f, fstate.path_len);
251 CALL_BACK(f, JSON_TYPE_STRING, fstate.ptr, f->cur - fstate.ptr);
252 f->cur++;
253 break;
257 return ch == '"' ? 0 : JSON_STRING_INCOMPLETE;
260 /* number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] */
261 static int json_parse_number(struct frozen *f) {
262 int ch = json_cur(f);
263 SET_STATE(f, f->cur, "", 0);
264 if (ch == '-') f->cur++;
265 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
266 if (f->cur + 1 < f->end && f->cur[0] == '0' && f->cur[1] == 'x') {
267 f->cur += 2;
268 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
269 EXPECT(json_isxdigit(f->cur[0]), JSON_STRING_INVALID);
270 while (f->cur < f->end && json_isxdigit(f->cur[0])) f->cur++;
271 } else {
272 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
273 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
274 if (f->cur < f->end && f->cur[0] == '.') {
275 f->cur++;
276 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
277 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
278 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
280 if (f->cur < f->end && (f->cur[0] == 'e' || f->cur[0] == 'E')) {
281 f->cur++;
282 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
283 if ((f->cur[0] == '+' || f->cur[0] == '-')) f->cur++;
284 EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE);
285 EXPECT(json_isdigit(f->cur[0]), JSON_STRING_INVALID);
286 while (f->cur < f->end && json_isdigit(f->cur[0])) f->cur++;
289 json_truncate_path(f, fstate.path_len);
290 CALL_BACK(f, JSON_TYPE_NUMBER, fstate.ptr, f->cur - fstate.ptr);
291 return 0;
294 #if JSON_ENABLE_ARRAY
295 /* array = '[' [ value { ',' value } ] ']' */
296 static int json_parse_array(struct frozen *f) {
297 int i = 0, current_path_len;
298 char buf[20];
299 CALL_BACK(f, JSON_TYPE_ARRAY_START, NULL, 0);
300 TRY(json_test_and_skip(f, '['));
303 SET_STATE(f, f->cur - 1, "", 0);
304 while (json_cur(f) != ']') {
305 snprintf(buf, sizeof(buf), "[%d]", i);
306 i++;
307 current_path_len = json_append_to_path(f, buf, strlen(buf));
308 f->cur_name =
309 f->path + strlen(f->path) - strlen(buf) + 1 /*opening brace*/;
310 f->cur_name_len = strlen(buf) - 2 /*braces*/;
311 TRY(json_parse_value(f));
312 json_truncate_path(f, current_path_len);
313 if (json_cur(f) == ',') f->cur++;
315 TRY(json_test_and_skip(f, ']'));
316 json_truncate_path(f, fstate.path_len);
317 CALL_BACK(f, JSON_TYPE_ARRAY_END, fstate.ptr, f->cur - fstate.ptr);
320 return 0;
322 #endif /* JSON_ENABLE_ARRAY */
324 static int json_expect(struct frozen *f, const char *s, int len,
325 enum json_token_type tok_type) {
326 int i, n = json_left(f);
327 SET_STATE(f, f->cur, "", 0);
328 for (i = 0; i < len; i++) {
329 if (i >= n) return JSON_STRING_INCOMPLETE;
330 if (f->cur[i] != s[i]) return JSON_STRING_INVALID;
332 f->cur += len;
333 json_truncate_path(f, fstate.path_len);
335 CALL_BACK(f, tok_type, fstate.ptr, f->cur - fstate.ptr);
337 return 0;
340 /* value = 'null' | 'true' | 'false' | number | string | array | object */
341 static int json_parse_value(struct frozen *f) {
342 int ch = json_cur(f);
344 switch (ch) {
345 case '"':
346 TRY(json_parse_string(f));
347 break;
348 case '{':
349 TRY(json_parse_object(f));
350 break;
351 #if JSON_ENABLE_ARRAY
352 case '[':
353 TRY(json_parse_array(f));
354 break;
355 #endif
356 case 'n':
357 TRY(json_expect(f, "null", 4, JSON_TYPE_NULL));
358 break;
359 case 't':
360 TRY(json_expect(f, "true", 4, JSON_TYPE_TRUE));
361 break;
362 case 'f':
363 TRY(json_expect(f, "false", 5, JSON_TYPE_FALSE));
364 break;
365 case '-':
366 case '0':
367 case '1':
368 case '2':
369 case '3':
370 case '4':
371 case '5':
372 case '6':
373 case '7':
374 case '8':
375 case '9':
376 TRY(json_parse_number(f));
377 break;
378 default:
379 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
382 return 0;
385 /* key = identifier | string */
386 static int json_parse_key(struct frozen *f) {
387 int ch = json_cur(f);
388 if (json_isalpha(ch)) {
389 TRY(json_parse_identifier(f));
390 } else if (ch == '"') {
391 TRY(json_parse_string(f));
392 } else {
393 return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
395 return 0;
398 /* pair = key ':' value */
399 static int json_parse_pair(struct frozen *f) {
400 int current_path_len;
401 const char *tok;
402 json_skip_whitespaces(f);
403 tok = f->cur;
404 TRY(json_parse_key(f));
406 f->cur_name = *tok == '"' ? tok + 1 : tok;
407 f->cur_name_len = *tok == '"' ? f->cur - tok - 2 : f->cur - tok;
408 current_path_len = json_append_to_path(f, f->cur_name, f->cur_name_len);
410 TRY(json_test_and_skip(f, ':'));
411 TRY(json_parse_value(f));
412 json_truncate_path(f, current_path_len);
413 return 0;
416 /* object = '{' pair { ',' pair } '}' */
417 static int json_parse_object(struct frozen *f) {
418 CALL_BACK(f, JSON_TYPE_OBJECT_START, NULL, 0);
419 TRY(json_test_and_skip(f, '{'));
421 SET_STATE(f, f->cur - 1, ".", 1);
422 while (json_cur(f) != '}') {
423 TRY(json_parse_pair(f));
424 if (json_cur(f) == ',') f->cur++;
426 TRY(json_test_and_skip(f, '}'));
427 json_truncate_path(f, fstate.path_len);
428 CALL_BACK(f, JSON_TYPE_OBJECT_END, fstate.ptr, f->cur - fstate.ptr);
430 return 0;
433 static int json_doit(struct frozen *f) {
434 if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID;
435 if (f->end == f->cur) return JSON_STRING_INCOMPLETE;
436 return json_parse_value(f);
439 int json_escape(struct json_out *out, const char *p, size_t len) WEAK;
440 int json_escape(struct json_out *out, const char *str, size_t str_len) {
441 size_t i, cl, n = 0;
442 const char *hex_digits = "0123456789abcdef";
443 const char *specials = "btnvfr";
445 for (i = 0; i < str_len; i++) {
446 unsigned char ch = ((unsigned char *) str)[i];
447 if (ch == '"' || ch == '\\') {
448 n += out->printer(out, "\\", 1);
449 n += out->printer(out, str + i, 1);
450 } else if (ch >= '\b' && ch <= '\r') {
451 n += out->printer(out, "\\", 1);
452 n += out->printer(out, &specials[ch - '\b'], 1);
453 } else if (c_isprint(ch)) {
454 n += out->printer(out, str + i, 1);
455 } else if ((cl = json_get_utf8_char_len(ch)) == 1) {
456 n += out->printer(out, "\\u00", 4);
457 n += out->printer(out, &hex_digits[(ch >> 4) % 0xf], 1);
458 n += out->printer(out, &hex_digits[ch % 0xf], 1);
459 } else {
460 n += out->printer(out, str + i, cl);
461 i += cl - 1;
465 return n;
468 int json_printer_buf(struct json_out *out, const char *buf, size_t len) WEAK;
469 int json_printer_buf(struct json_out *out, const char *buf, size_t len) {
470 size_t avail = out->u.buf.size - out->u.buf.len;
471 size_t n = len < avail ? len : avail;
472 memcpy(out->u.buf.buf + out->u.buf.len, buf, n);
473 out->u.buf.len += n;
474 if (out->u.buf.size > 0) {
475 size_t idx = out->u.buf.len;
476 if (idx >= out->u.buf.size) idx = out->u.buf.size - 1;
477 out->u.buf.buf[idx] = '\0';
479 return len;
482 int json_printer_file(struct json_out *out, const char *buf, size_t len) WEAK;
483 int json_printer_file(struct json_out *out, const char *buf, size_t len) {
484 return fwrite(buf, 1, len, out->u.fp);
487 #if JSON_ENABLE_BASE64
488 static int b64idx(int c) {
489 if (c < 26) {
490 return c + 'A';
491 } else if (c < 52) {
492 return c - 26 + 'a';
493 } else if (c < 62) {
494 return c - 52 + '0';
495 } else {
496 return c == 62 ? '+' : '/';
500 static int b64rev(int c) {
501 if (c >= 'A' && c <= 'Z') {
502 return c - 'A';
503 } else if (c >= 'a' && c <= 'z') {
504 return c + 26 - 'a';
505 } else if (c >= '0' && c <= '9') {
506 return c + 52 - '0';
507 } else if (c == '+') {
508 return 62;
509 } else if (c == '/') {
510 return 63;
511 } else {
512 return 64;
516 static int b64enc(struct json_out *out, const unsigned char *p, int n) {
517 char buf[4];
518 int i, len = 0;
519 for (i = 0; i < n; i += 3) {
520 int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0;
521 buf[0] = b64idx(a >> 2);
522 buf[1] = b64idx((a & 3) << 4 | (b >> 4));
523 buf[2] = b64idx((b & 15) << 2 | (c >> 6));
524 buf[3] = b64idx(c & 63);
525 if (i + 1 >= n) buf[2] = '=';
526 if (i + 2 >= n) buf[3] = '=';
527 len += out->printer(out, buf, sizeof(buf));
529 return len;
532 static int b64dec(const char *src, int n, char *dst) {
533 const char *end = src + n;
534 int len = 0;
535 while (src + 3 < end) {
536 int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]),
537 d = b64rev(src[3]);
538 dst[len++] = (a << 2) | (b >> 4);
539 if (src[2] != '=') {
540 dst[len++] = (b << 4) | (c >> 2);
541 if (src[3] != '=') {
542 dst[len++] = (c << 6) | d;
545 src += 4;
547 return len;
549 #endif /* JSON_ENABLE_BASE64 */
551 static unsigned char hexdec(const char *s) {
552 #define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W')
553 int a = c_tolower(*(const unsigned char *) s);
554 int b = c_tolower(*(const unsigned char *)(s + 1));
555 return (HEXTOI(a) << 4) | HEXTOI(b);
558 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) WEAK;
559 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
560 int len = 0;
561 const char *quote = "\"", *null = "null";
562 va_list ap;
563 va_copy(ap, xap);
565 while (*fmt != '\0') {
566 if (strchr(":, \r\n\t[]{}\"", *fmt) != NULL) {
567 len += out->printer(out, fmt, 1);
568 fmt++;
569 } else if (fmt[0] == '%') {
570 char buf[21];
571 size_t skip = 2;
573 if (fmt[1] == 'l' && fmt[2] == 'l' && (fmt[3] == 'd' || fmt[3] == 'u')) {
574 int64_t val = va_arg(ap, int64_t);
575 const char *fmt2 = fmt[3] == 'u' ? "%" UINT64_FMT : "%" INT64_FMT;
576 snprintf(buf, sizeof(buf), fmt2, val);
577 len += out->printer(out, buf, strlen(buf));
578 skip += 2;
579 } else if (fmt[1] == 'z' && fmt[2] == 'u') {
580 size_t val = va_arg(ap, size_t);
581 snprintf(buf, sizeof(buf), "%lu", (unsigned long) val);
582 len += out->printer(out, buf, strlen(buf));
583 skip += 1;
584 } else if (fmt[1] == 'M') {
585 json_printf_callback_t f = va_arg(ap, json_printf_callback_t);
586 len += f(out, &ap);
587 } else if (fmt[1] == 'B') {
588 int val = va_arg(ap, int);
589 const char *str = val ? "true" : "false";
590 len += out->printer(out, str, strlen(str));
591 } else if (fmt[1] == 'H') {
592 #if JSON_ENABLE_HEX
593 const char *hex = "0123456789abcdef";
594 int i, n = va_arg(ap, int);
595 const unsigned char *p = va_arg(ap, const unsigned char *);
596 len += out->printer(out, quote, 1);
597 for (i = 0; i < n; i++) {
598 len += out->printer(out, &hex[(p[i] >> 4) & 0xf], 1);
599 len += out->printer(out, &hex[p[i] & 0xf], 1);
601 len += out->printer(out, quote, 1);
602 #endif /* JSON_ENABLE_HEX */
603 } else if (fmt[1] == 'V') {
604 #if JSON_ENABLE_BASE64
605 const unsigned char *p = va_arg(ap, const unsigned char *);
606 int n = va_arg(ap, int);
607 len += out->printer(out, quote, 1);
608 len += b64enc(out, p, n);
609 len += out->printer(out, quote, 1);
610 #endif /* JSON_ENABLE_BASE64 */
611 } else if (fmt[1] == 'Q' ||
612 (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) {
613 size_t l = 0;
614 const char *p;
616 if (fmt[1] == '.') {
617 l = (size_t) va_arg(ap, int);
618 skip += 2;
620 p = va_arg(ap, char *);
622 if (p == NULL) {
623 len += out->printer(out, null, 4);
624 } else {
625 if (fmt[1] == 'Q') {
626 l = strlen(p);
628 len += out->printer(out, quote, 1);
629 len += json_escape(out, p, l);
630 len += out->printer(out, quote, 1);
632 } else {
634 * we delegate printing to the system printf.
635 * The goal here is to delegate all modifiers parsing to the system
636 * printf, as you can see below we still have to parse the format
637 * types.
639 * Currently, %s with strings longer than 20 chars will require
640 * double-buffering (an auxiliary buffer will be allocated from heap).
641 * TODO(dfrank): reimplement %s and %.*s in order to avoid that.
644 const char *end_of_format_specifier = "sdfFeEgGlhuIcx.*-0123456789";
645 int n = strspn(fmt + 1, end_of_format_specifier);
646 char *pbuf = buf;
647 int need_len, size = sizeof(buf);
648 char fmt2[20];
649 va_list ap_copy;
650 strncpy(fmt2, fmt,
651 n + 1 > (int) sizeof(fmt2) ? sizeof(fmt2) : (size_t) n + 1);
652 fmt2[n + 1] = '\0';
654 va_copy(ap_copy, ap);
655 need_len = vsnprintf(pbuf, size, fmt2, ap_copy);
656 va_end(ap_copy);
658 if (need_len < 0) {
660 * Windows & eCos vsnprintf implementation return -1 on overflow
661 * instead of needed size.
663 pbuf = NULL;
664 while (need_len < 0) {
665 free(pbuf);
666 size *= 2;
667 if ((pbuf = (char *) malloc(size)) == NULL) break;
668 va_copy(ap_copy, ap);
669 need_len = vsnprintf(pbuf, size, fmt2, ap_copy);
670 va_end(ap_copy);
672 } else if (need_len >= (int) sizeof(buf)) {
674 * resulting string doesn't fit into a stack-allocated buffer `buf`,
675 * so we need to allocate a new buffer from heap and use it
677 if ((pbuf = (char *) malloc(need_len + 1)) != NULL) {
678 va_copy(ap_copy, ap);
679 vsnprintf(pbuf, need_len + 1, fmt2, ap_copy);
680 va_end(ap_copy);
683 if (pbuf == NULL) {
684 buf[0] = '\0';
685 pbuf = buf;
689 * however we need to parse the type ourselves in order to advance
690 * the va_list by the correct amount; there is no portable way to
691 * inherit the advancement made by vprintf.
692 * 32-bit (linux or windows) passes va_list by value.
694 if ((n + 1 == strlen("%" PRId64) && strcmp(fmt2, "%" PRId64) == 0) ||
695 (n + 1 == strlen("%" PRIu64) && 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);
719 len += out->printer(out, pbuf, strlen(pbuf));
720 skip = n + 1;
722 /* If buffer was allocated from heap, free it */
723 if (pbuf != buf) {
724 free(pbuf);
725 pbuf = NULL;
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++;
735 len += out->printer(out, quote, 1);
736 } else {
737 len += out->printer(out, fmt, 1);
738 fmt++;
741 va_end(ap);
743 return len;
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;
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);
778 len += json_printf(out, "]", 1);
779 return len;
782 #ifdef _WIN32
783 int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap) WEAK;
784 int cs_win_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
785 int res = _vsnprintf(str, size, format, ap);
786 va_end(ap);
787 if (res >= size) {
788 str[size - 1] = '\0';
790 return res;
793 int cs_win_snprintf(char *str, size_t size, const char *format, ...) WEAK;
794 int cs_win_snprintf(char *str, size_t size, const char *format, ...) {
795 int res;
796 va_list ap;
797 va_start(ap, format);
798 res = vsnprintf(str, size, format, ap);
799 va_end(ap);
800 return res;
802 #endif /* _WIN32 */
804 int json_walk(const char *json_string, int json_string_length,
805 json_walk_callback_t callback, void *callback_data) WEAK;
806 int json_walk(const char *json_string, int json_string_length,
807 json_walk_callback_t callback, void *callback_data) {
808 struct frozen frozen;
810 memset(&frozen, 0, sizeof(frozen));
811 frozen.end = json_string + json_string_length;
812 frozen.cur = json_string;
813 frozen.callback_data = callback_data;
814 frozen.callback = callback;
816 TRY(json_doit(&frozen));
818 return frozen.cur - json_string;
821 struct scan_array_info {
822 int found;
823 char path[JSON_MAX_PATH_LEN];
824 struct json_token *token;
827 static void json_scanf_array_elem_cb(void *callback_data, const char *name,
828 size_t name_len, const char *path,
829 const struct json_token *token) {
830 struct scan_array_info *info = (struct scan_array_info *) callback_data;
832 (void) name;
833 (void) name_len;
835 if (strcmp(path, info->path) == 0) {
836 *info->token = *token;
837 info->found = 1;
841 int json_scanf_array_elem(const char *s, int len, const char *path, int idx,
842 struct json_token *token) WEAK;
843 int json_scanf_array_elem(const char *s, int len, const char *path, int idx,
844 struct json_token *token) {
845 struct scan_array_info info;
846 info.token = token;
847 info.found = 0;
848 memset(token, 0, sizeof(*token));
849 snprintf(info.path, sizeof(info.path), "%s[%d]", path, idx);
850 json_walk(s, len, json_scanf_array_elem_cb, &info);
851 return info.found ? token->len : -1;
854 struct json_scanf_info {
855 int num_conversions;
856 char *path;
857 const char *fmt;
858 void *target;
859 void *user_data;
860 int type;
863 int json_unescape(const char *src, int slen, char *dst, int dlen) WEAK;
864 int json_unescape(const char *src, int slen, char *dst, int dlen) {
865 if (dst == NULL || dlen == 0)
866 return JSON_STRING_INVALID;
868 char *send = (char *) src + slen;
869 char *dend = dst + dlen;
870 char *orig_dst = dst;
871 char *p;
872 const char *esc1 = "\"\\/bfnrt", *esc2 = "\"\\/\b\f\n\r\t";
874 while (src < send) {
875 if (*src == '\\') {
876 if (++src >= send) { return JSON_STRING_INCOMPLETE; }
878 if (*src == 'u') {
879 if (send - src < 5) { return JSON_STRING_INCOMPLETE; }
880 /* Here we go: this is a \u.... escape. Process simple one-byte chars */
881 if (src[1] == '0' && src[2] == '0') {
882 /* This is \u00xx character from the ASCII range */
883 if (dst < dend) *dst = hexdec(src + 3);
884 src += 4;
885 } else {
886 /* Complex \uXXXX escapes drag utf8 lib... Do it at some stage */
887 return JSON_STRING_INVALID;
889 } else if ((p = (char *) strchr(esc1, *src)) != NULL) {
890 if (dst < dend) {
891 *dst = esc2[p - esc1];
893 } else {
894 return JSON_STRING_INVALID;
896 } else {
897 if (dst < dend) {
898 *dst = *src;
901 dst++;
902 src++;
905 return dst - orig_dst;
908 static void json_scanf_cb(void *callback_data, const char *name,
909 size_t name_len, const char *path,
910 const struct json_token *token) {
911 struct json_scanf_info *info = (struct json_scanf_info *) callback_data;
912 char buf[32]; /* Must be enough to hold numbers */
914 (void) name;
915 (void) name_len;
917 if (token->ptr == NULL) {
919 * We're not interested here in the events for which we have no value;
920 * namely, JSON_TYPE_OBJECT_START and JSON_TYPE_ARRAY_START
922 return;
925 if (strcmp(path, info->path) != 0) {
926 /* It's not the path we're looking for, so, just ignore this callback */
927 return;
930 switch (info->type) {
931 case 'B':
932 info->num_conversions++;
933 switch (sizeof(bool)) {
934 case sizeof(char):
935 *(char *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0);
936 break;
937 case sizeof(int):
938 *(int *) info->target = (token->type == JSON_TYPE_TRUE ? 1 : 0);
939 break;
940 default:
941 /* should never be here */
942 abort();
944 break;
945 case 'M': {
946 union {
947 void *p;
948 json_scanner_t f;
949 } u = {info->target};
950 info->num_conversions++;
951 u.f(token->ptr, token->len, info->user_data);
952 break;
954 case 'Q': {
955 char **dst = (char **) info->target;
956 if (token->type == JSON_TYPE_NULL) {
957 *dst = NULL;
958 } else {
959 int unescaped_len = json_unescape(token->ptr, token->len, NULL, 0);
960 if (unescaped_len >= 0 &&
961 (*dst = (char *) malloc(unescaped_len + 1)) != NULL) {
962 info->num_conversions++;
963 if (json_unescape(token->ptr, token->len, *dst, unescaped_len) ==
964 unescaped_len) {
965 (*dst)[unescaped_len] = '\0';
966 } else {
967 free(*dst);
968 *dst = NULL;
972 break;
974 case 'H': {
975 #if JSON_ENABLE_HEX
976 char **dst = (char **) info->user_data;
977 int i, len = token->len / 2;
978 *(int *) info->target = len;
979 if ((*dst = (char *) malloc(len + 1)) != NULL) {
980 for (i = 0; i < len; i++) {
981 (*dst)[i] = hexdec(token->ptr + 2 * i);
983 (*dst)[len] = '\0';
984 info->num_conversions++;
986 #endif /* JSON_ENABLE_HEX */
987 break;
989 case 'V': {
990 #if JSON_ENABLE_BASE64
991 char **dst = (char **) info->target;
992 int len = token->len * 4 / 3 + 2;
993 if ((*dst = (char *) malloc(len + 1)) != NULL) {
994 int n = b64dec(token->ptr, token->len, *dst);
995 (*dst)[n] = '\0';
996 *(int *) info->user_data = n;
997 info->num_conversions++;
999 #endif /* JSON_ENABLE_BASE64 */
1000 break;
1002 case 'T':
1003 info->num_conversions++;
1004 *(struct json_token *) info->target = *token;
1005 break;
1006 default:
1007 if (token->len >= (int) sizeof(buf)) break;
1008 /* Before converting, copy into tmp buffer in order to 0-terminate it */
1009 memcpy(buf, token->ptr, token->len);
1010 buf[token->len] = '\0';
1011 /* NB: Use of base 0 for %d, %ld, %u and %lu is intentional. */
1012 if (info->fmt[1] == 'd' || (info->fmt[1] == 'l' && info->fmt[2] == 'd') ||
1013 info->fmt[1] == 'i') {
1014 char *endptr = NULL;
1015 long r = strtol(buf, &endptr, 0 /* base */);
1016 if (*endptr == '\0') {
1017 if (info->fmt[1] == 'l') {
1018 *((long *) info->target) = r;
1019 } else {
1020 *((int *) info->target) = (int) r;
1022 info->num_conversions++;
1024 } else if (info->fmt[1] == 'u' ||
1025 (info->fmt[1] == 'l' && info->fmt[2] == 'u')) {
1026 char *endptr = NULL;
1027 unsigned long r = strtoul(buf, &endptr, 0 /* base */);
1028 if (*endptr == '\0') {
1029 if (info->fmt[1] == 'l') {
1030 *((unsigned long *) info->target) = r;
1031 } else {
1032 *((unsigned int *) info->target) = (unsigned int) r;
1034 info->num_conversions++;
1036 } else {
1037 #if !JSON_MINIMAL
1038 info->num_conversions += sscanf(buf, info->fmt, info->target);
1039 #endif
1041 break;
1045 int json_vscanf(const char *str, int len, const char *fmt, va_list ap) WEAK;
1046 int json_vscanf(const char *str, int len, const char *fmt, va_list ap) {
1047 char path[JSON_MAX_PATH_LEN] = "", fmtbuf[20];
1048 int i = 0;
1049 char *p = NULL;
1050 struct json_scanf_info info = {0, path, fmtbuf, NULL, NULL, 0};
1052 while (fmt[i] != '\0') {
1053 if (fmt[i] == '{') {
1054 strcat(path, ".");
1055 i++;
1056 } else if (fmt[i] == '}') {
1057 if ((p = strrchr(path, '.')) != NULL) * p = '\0';
1058 i++;
1059 } else if (fmt[i] == '%') {
1060 info.target = va_arg(ap, void *);
1061 info.type = fmt[i + 1];
1062 switch (fmt[i + 1]) {
1063 case 'M':
1064 case 'V':
1065 case 'H':
1066 info.user_data = va_arg(ap, void *);
1067 /* FALLTHROUGH */
1068 case 'B':
1069 case 'Q':
1070 case 'T':
1071 i += 2;
1072 break;
1073 default: {
1074 const char *delims = ", \t\r\n]}";
1075 int conv_len = strcspn(fmt + i + 1, delims) + 1;
1076 memcpy(fmtbuf, fmt + i, conv_len);
1077 fmtbuf[conv_len] = '\0';
1078 i += conv_len;
1079 i += strspn(fmt + i, delims);
1080 break;
1083 json_walk(str, len, json_scanf_cb, &info);
1084 } else if (json_isalpha(fmt[i]) || json_get_utf8_char_len(fmt[i]) > 1) {
1085 char *pe;
1086 const char *delims = ": \r\n\t";
1087 int key_len = strcspn(&fmt[i], delims);
1088 if ((p = strrchr(path, '.')) != NULL) p[1] = '\0';
1089 pe = path + strlen(path);
1090 memcpy(pe, fmt + i, key_len);
1091 pe[key_len] = '\0';
1092 i += key_len + strspn(fmt + i + key_len, delims);
1093 } else {
1094 i++;
1097 return info.num_conversions;
1100 int json_scanf(const char *str, int len, const char *fmt, ...) WEAK;
1101 int json_scanf(const char *str, int len, const char *fmt, ...) {
1102 int result;
1103 va_list ap;
1104 va_start(ap, fmt);
1105 result = json_vscanf(str, len, fmt, ap);
1106 va_end(ap);
1107 return result;
1110 int json_vfprintf(const char *file_name, const char *fmt, va_list ap) WEAK;
1111 int json_vfprintf(const char *file_name, const char *fmt, va_list ap) {
1112 int res = -1;
1113 FILE *fp = fopen(file_name, "wb");
1114 if (fp != NULL) {
1115 struct json_out out = JSON_OUT_FILE(fp);
1116 res = json_vprintf(&out, fmt, ap);
1117 fputc('\n', fp);
1118 fclose(fp);
1120 return res;
1123 int json_fprintf(const char *file_name, const char *fmt, ...) WEAK;
1124 int json_fprintf(const char *file_name, const char *fmt, ...) {
1125 int result;
1126 va_list ap;
1127 va_start(ap, fmt);
1128 result = json_vfprintf(file_name, fmt, ap);
1129 va_end(ap);
1130 return result;
1133 char *json_fread(const char *path) WEAK;
1134 char *json_fread(const char *path) {
1135 FILE *fp;
1136 char *data = NULL;
1137 if ((fp = fopen(path, "rb")) == NULL) {
1138 } else if (fseek(fp, 0, SEEK_END) != 0) {
1139 fclose(fp);
1140 } else {
1141 long size = ftell(fp);
1142 if (size > 0 && (data = (char *) malloc(size + 1)) != NULL) {
1143 fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
1144 if (fread(data, 1, size, fp) != (size_t) size) {
1145 free(data);
1146 data = NULL;
1147 } else {
1148 data[size] = '\0';
1151 fclose(fp);
1153 return data;
1156 struct json_setf_data {
1157 const char *json_path;
1158 const char *base; /* Pointer to the source JSON string */
1159 int matched; /* Matched part of json_path */
1160 int pos; /* Offset of the mutated value begin */
1161 int end; /* Offset of the mutated value end */
1162 int prev; /* Offset of the previous token end */
1165 static int get_matched_prefix_len(const char *s1, const char *s2) {
1166 int i = 0;
1167 while (s1[i] && s2[i] && s1[i] == s2[i]) i++;
1168 return i;
1171 static void json_vsetf_cb(void *userdata, const char *name, size_t name_len,
1172 const char *path, const struct json_token *t) {
1173 struct json_setf_data *data = (struct json_setf_data *) userdata;
1174 int off, len = get_matched_prefix_len(path, data->json_path);
1175 if (t->ptr == NULL) return;
1176 off = t->ptr - data->base;
1177 if (len > data->matched) data->matched = len;
1180 * If there is no exact path match, set the mutation position to tbe end
1181 * of the object or array
1183 if (len < data->matched && data->pos == 0 &&
1184 (t->type == JSON_TYPE_OBJECT_END || t->type == JSON_TYPE_ARRAY_END)) {
1185 data->pos = data->end = data->prev;
1188 /* Exact path match. Set mutation position to the value of this token */
1189 if (strcmp(path, data->json_path) == 0 && t->type != JSON_TYPE_OBJECT_START &&
1190 t->type != JSON_TYPE_ARRAY_START) {
1191 data->pos = off;
1192 data->end = off + t->len;
1196 * For deletion, we need to know where the previous value ends, because
1197 * we don't know where matched value key starts.
1198 * When the mutation position is not yet set, remember each value end.
1199 * When the mutation position is already set, but it is at the beginning
1200 * of the object/array, we catch the end of the object/array and see
1201 * whether the object/array start is closer then previously stored prev.
1203 if (data->pos == 0) {
1204 data->prev = off + t->len; /* pos is not yet set */
1205 } else if ((t->ptr[0] == '[' || t->ptr[0] == '{') && off + 1 < data->pos &&
1206 off + 1 > data->prev) {
1207 data->prev = off + 1;
1209 (void) name;
1210 (void) name_len;
1213 int json_vsetf(const char *s, int len, struct json_out *out,
1214 const char *json_path, const char *json_fmt, va_list ap) WEAK;
1215 int json_vsetf(const char *s, int len, struct json_out *out,
1216 const char *json_path, const char *json_fmt, va_list ap) {
1217 struct json_setf_data data;
1218 memset(&data, 0, sizeof(data));
1219 data.json_path = json_path;
1220 data.base = s;
1221 data.end = len;
1222 json_walk(s, len, json_vsetf_cb, &data);
1223 if (json_fmt == NULL) {
1224 /* Deletion codepath */
1225 json_printf(out, "%.*s", data.prev, s);
1226 /* Trim comma after the value that begins at object/array start */
1227 if (s[data.prev - 1] == '{' || s[data.prev - 1] == '[') {
1228 int i = data.end;
1229 while (i < len && json_isspace(s[i])) i++;
1230 if (s[i] == ',') data.end = i + 1; /* Point after comma */
1232 json_printf(out, "%.*s", len - data.end, s + data.end);
1233 } else {
1234 /* Modification codepath */
1235 int n, off = data.matched, depth = 0;
1237 /* Print the unchanged beginning */
1238 json_printf(out, "%.*s", data.pos, s);
1240 /* Add missing keys */
1241 while ((n = strcspn(&json_path[off], ".[")) > 0) {
1242 if (s[data.prev - 1] != '{' && s[data.prev - 1] != '[' && depth == 0) {
1243 json_printf(out, ",");
1245 if (off > 0 && json_path[off - 1] != '.') break;
1246 json_printf(out, "%.*Q:", n, json_path + off);
1247 off += n;
1248 if (json_path[off] != '\0') {
1249 json_printf(out, "%c", json_path[off] == '.' ? '{' : '[');
1250 depth++;
1251 off++;
1254 /* Print the new value */
1255 json_vprintf(out, json_fmt, ap);
1257 /* Close brackets/braces of the added missing keys */
1258 for (; off > data.matched; off--) {
1259 int ch = json_path[off];
1260 const char *p = ch == '.' ? "}" : ch == '[' ? "]" : "";
1261 json_printf(out, "%s", p);
1264 /* Print the rest of the unchanged string */
1265 json_printf(out, "%.*s", len - data.end, s + data.end);
1267 return data.end > data.pos ? 1 : 0;
1270 int json_setf(const char *s, int len, struct json_out *out,
1271 const char *json_path, const char *json_fmt, ...) WEAK;
1272 int json_setf(const char *s, int len, struct json_out *out,
1273 const char *json_path, const char *json_fmt, ...) {
1274 int result;
1275 va_list ap;
1276 va_start(ap, json_fmt);
1277 result = json_vsetf(s, len, out, json_path, json_fmt, ap);
1278 va_end(ap);
1279 return result;
1282 struct prettify_data {
1283 struct json_out *out;
1284 int level;
1285 int last_token;
1288 static void indent(struct json_out *out, int level) {
1289 while (level-- > 0) out->printer(out, " ", 2);
1292 static void print_key(struct prettify_data *pd, const char *path,
1293 const char *name, int name_len) {
1294 if (pd->last_token != JSON_TYPE_INVALID &&
1295 pd->last_token != JSON_TYPE_ARRAY_START &&
1296 pd->last_token != JSON_TYPE_OBJECT_START) {
1297 pd->out->printer(pd->out, ",", 1);
1299 if (path[0] != '\0') pd->out->printer(pd->out, "\n", 1);
1300 indent(pd->out, pd->level);
1301 if (path[0] != '\0' && path[strlen(path) - 1] != ']') {
1302 pd->out->printer(pd->out, "\"", 1);
1303 pd->out->printer(pd->out, name, (int) name_len);
1304 pd->out->printer(pd->out, "\"", 1);
1305 pd->out->printer(pd->out, ": ", 2);
1309 static void prettify_cb(void *userdata, const char *name, size_t name_len,
1310 const char *path, const struct json_token *t) {
1311 struct prettify_data *pd = (struct prettify_data *) userdata;
1312 switch (t->type) {
1313 case JSON_TYPE_OBJECT_START:
1314 case JSON_TYPE_ARRAY_START:
1315 print_key(pd, path, name, name_len);
1316 pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_START ? "[" : "{",
1318 pd->level++;
1319 break;
1320 case JSON_TYPE_OBJECT_END:
1321 case JSON_TYPE_ARRAY_END:
1322 pd->level--;
1323 if (pd->last_token != JSON_TYPE_INVALID &&
1324 pd->last_token != JSON_TYPE_ARRAY_START &&
1325 pd->last_token != JSON_TYPE_OBJECT_START) {
1326 pd->out->printer(pd->out, "\n", 1);
1327 indent(pd->out, pd->level);
1329 pd->out->printer(pd->out, t->type == JSON_TYPE_ARRAY_END ? "]" : "}", 1);
1330 break;
1331 case JSON_TYPE_NUMBER:
1332 case JSON_TYPE_NULL:
1333 case JSON_TYPE_TRUE:
1334 case JSON_TYPE_FALSE:
1335 case JSON_TYPE_STRING:
1336 print_key(pd, path, name, name_len);
1337 if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1);
1338 pd->out->printer(pd->out, t->ptr, t->len);
1339 if (t->type == JSON_TYPE_STRING) pd->out->printer(pd->out, "\"", 1);
1340 break;
1341 default:
1342 break;
1344 pd->last_token = t->type;
1347 int json_prettify(const char *s, int len, struct json_out *out) WEAK;
1348 int json_prettify(const char *s, int len, struct json_out *out) {
1349 struct prettify_data pd = {out, 0, JSON_TYPE_INVALID};
1350 return json_walk(s, len, prettify_cb, &pd);
1353 int json_prettify_file(const char *file_name) WEAK;
1354 int json_prettify_file(const char *file_name) {
1355 int res = -1;
1356 char *s = json_fread(file_name);
1357 FILE *fp;
1358 if (s != NULL && (fp = fopen(file_name, "wb")) != NULL) {
1359 struct json_out out = JSON_OUT_FILE(fp);
1360 res = json_prettify(s, strlen(s), &out);
1361 if (res < 0) {
1362 /* On error, restore the old content */
1363 fclose(fp);
1364 fp = fopen(file_name, "wb");
1365 fseek(fp, 0, SEEK_SET);
1366 fwrite(s, 1, strlen(s), fp);
1367 } else {
1368 fputc('\n', fp);
1370 fclose(fp);
1372 free(s);
1373 return res;
1376 struct next_data {
1377 void *handle; // Passed handle. Changed if a next entry is found
1378 const char *path; // Path to the iterated object/array
1379 int path_len; // Path length - optimisation
1380 int found; // Non-0 if found the next entry
1381 struct json_token *key; // Object's key
1382 struct json_token *val; // Object's value
1383 int *idx; // Array index
1386 static void next_set_key(struct next_data *d, const char *name, int name_len,
1387 int is_array) {
1388 if (is_array) {
1389 /* Array. Set index and reset key */
1390 if (d->key != NULL) {
1391 d->key->len = 0;
1392 d->key->ptr = NULL;
1394 if (d->idx != NULL) *d->idx = atoi(name);
1395 } else {
1396 /* Object. Set key and make index -1 */
1397 if (d->key != NULL) {
1398 d->key->ptr = name;
1399 d->key->len = name_len;
1401 if (d->idx != NULL) *d->idx = -1;
1405 static void json_next_cb(void *userdata, const char *name, size_t name_len,
1406 const char *path, const struct json_token *t) {
1407 struct next_data *d = (struct next_data *) userdata;
1408 const char *p = path + d->path_len;
1409 if (d->found) return;
1410 if (d->path_len >= (int) strlen(path)) return;
1411 if (strncmp(d->path, path, d->path_len) != 0) return;
1412 if (strchr(p + 1, '.') != NULL) return; /* More nested objects - skip */
1413 if (strchr(p + 1, '[') != NULL) return; /* Ditto for arrays */
1414 // {OBJECT,ARRAY}_END types do not pass name, _START does. Save key.
1415 if (t->type == JSON_TYPE_OBJECT_START || t->type == JSON_TYPE_ARRAY_START) {
1416 next_set_key(d, name, name_len, p[0] == '[');
1417 } else if (d->handle == NULL || d->handle < (void *) t->ptr) {
1418 if (t->type != JSON_TYPE_OBJECT_END && t->type != JSON_TYPE_ARRAY_END) {
1419 next_set_key(d, name, name_len, p[0] == '[');
1421 if (d->val != NULL) *d->val = *t;
1422 d->handle = (void *) t->ptr;
1423 d->found = 1;
1427 static void *json_next(const char *s, int len, void *handle, const char *path,
1428 struct json_token *key, struct json_token *val, int *i) {
1429 struct json_token tmpval, *v = val == NULL ? &tmpval : val;
1430 struct json_token tmpkey, *k = key == NULL ? &tmpkey : key;
1431 int tmpidx, *pidx = i == NULL ? &tmpidx : i;
1432 struct next_data data = {handle, path, (int) strlen(path), 0, k, v, pidx};
1433 json_walk(s, len, json_next_cb, &data);
1434 return data.found ? data.handle : NULL;
1437 void *json_next_key(const char *s, int len, void *handle, const char *path,
1438 struct json_token *key, struct json_token *val) WEAK;
1439 void *json_next_key(const char *s, int len, void *handle, const char *path,
1440 struct json_token *key, struct json_token *val) {
1441 return json_next(s, len, handle, path, key, val, NULL);
1444 void *json_next_elem(const char *s, int len, void *handle, const char *path,
1445 int *idx, struct json_token *val) WEAK;
1446 void *json_next_elem(const char *s, int len, void *handle, const char *path,
1447 int *idx, struct json_token *val) {
1448 return json_next(s, len, handle, path, NULL, val, idx);
1451 static int json_sprinter(struct json_out *out, const char *str, size_t len) {
1452 size_t old_len = out->u.buf.buf == NULL ? 0 : strlen(out->u.buf.buf);
1453 size_t new_len = len + old_len;
1454 char *p = (char *) realloc(out->u.buf.buf, new_len + 1);
1455 if (p != NULL) {
1456 memcpy(p + old_len, str, len);
1457 p[new_len] = '\0';
1458 out->u.buf.buf = p;
1460 return len;
1463 char *json_vasprintf(const char *fmt, va_list ap) WEAK;
1464 char *json_vasprintf(const char *fmt, va_list ap) {
1465 struct json_out out;
1466 memset(&out, 0, sizeof(out));
1467 out.printer = json_sprinter;
1468 json_vprintf(&out, fmt, ap);
1469 return out.u.buf.buf;
1472 char *json_asprintf(const char *fmt, ...) WEAK;
1473 char *json_asprintf(const char *fmt, ...) {
1474 va_list ap;
1475 va_start(ap, fmt);
1476 char *result = json_vasprintf(fmt, ap);
1477 va_end(ap);
1478 return result;