1 /*
2 * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
3 * https://github.com/udp/json-parser
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #ifndef json_char
30 #define json_char char
31 #endif
32
33 #ifndef json_int_t
34 #ifndef _MSC_VER
35 #include <inttypes.h>
36 #define json_int_t int64_t
37 #else
38 #define json_int_t __int64
39 #endif
40 #endif
41
42 #include <stdlib.h>
43
44 typedef struct
45 {
46 unsigned long max_memory;
47 int settings;
48
49 /* Custom allocator support (leave null to use malloc/free)
50 */
51
52 void * (* mem_alloc) (size_t, int zero, void * user_data);
53 void (* mem_free) (void *, void * user_data);
54
55 void * user_data; /* will be passed to mem_alloc and mem_free */
56
57 size_t value_extra; /* how much extra space to allocate for values? */
58
59 } json_settings;
60
61 typedef enum
62 {
63 json_none,
64 json_object,
65 json_array,
66 json_integer,
67 json_double,
68 json_string,
69 json_boolean,
70 json_null
71
72 } json_type;
73
74 extern const struct _json_value json_value_none;
75
76 typedef struct _json_object_entry
77 {
78 json_char * name;
79 unsigned int name_length;
80
81 struct _json_value * value;
82
83 } json_object_entry;
84
85 typedef struct _json_value
86 {
87 struct _json_value * parent;
88
89 json_type type;
90
91 union
92 {
93 int boolean;
94 json_int_t integer;
95 double dbl;
96
97 struct
98 {
99 unsigned int length;
100 json_char * ptr; /* null terminated */
101
102 } string;
103
104 struct
105 {
106 unsigned int length;
107
108 json_object_entry * values;
109
110 } object;
111
112 struct
113 {
114 unsigned int length;
115 struct _json_value ** values;
116
117 } array;
118
119 } u;
120
121 union
122 {
123 struct _json_value * next_alloc;
124 void * object_mem;
125
126 } _reserved;
127 } json_value;
128
129 json_value * json_parse (const json_char * json,
130 size_t length);
131
132 #define json_error_max 128
133 json_value * json_parse_ex (json_settings * settings,
134 const json_char * json,
135 size_t length,
136 char * error);
137
138 /* Not usually necessary, unless you used a custom mem_alloc and now want to
139 * use a custom mem_free.
140 */
141 void json_value_free_ex (json_settings * settings,
142 json_value *);
143
144
145
146 #ifdef _MSC_VER
147 #ifndef _CRT_SECURE_NO_WARNINGS
148 #define _CRT_SECURE_NO_WARNINGS
149 #endif
150 #endif
151
152 const struct _json_value json_value_none;
153
154 #include <stdio.h>
155 #include <string.h>
156 #include <ctype.h>
157
158 typedef unsigned int json_uchar;
159
hex_value(json_char c)160 static unsigned char hex_value (json_char c)
161 {
162 if (isdigit(c))
163 return c - '0';
164
165 switch (c) {
166 case 'a': case 'A': return 0x0A;
167 case 'b': case 'B': return 0x0B;
168 case 'c': case 'C': return 0x0C;
169 case 'd': case 'D': return 0x0D;
170 case 'e': case 'E': return 0x0E;
171 case 'f': case 'F': return 0x0F;
172 default: return 0xFF;
173 }
174 }
175
176 typedef struct
177 {
178 unsigned long used_memory;
179
180 unsigned int uint_max;
181 unsigned long ulong_max;
182
183 json_settings settings;
184 int first_pass;
185
186 const json_char * ptr;
187 unsigned int cur_line, cur_col;
188
189 } json_state;
190
default_alloc(size_t size,int zero,void * user_data)191 static void * default_alloc (size_t size, int zero, void * user_data)
192 {
193 return zero ? calloc (1, size) : malloc (size);
194 }
195
default_free(void * ptr,void * user_data)196 static void default_free (void * ptr, void * user_data)
197 {
198 free (ptr);
199 }
200
json_alloc(json_state * state,unsigned long size,int zero)201 static void * json_alloc (json_state * state, unsigned long size, int zero)
202 {
203 if ((state->ulong_max - state->used_memory) < size)
204 return 0;
205
206 if (state->settings.max_memory
207 && (state->used_memory += size) > state->settings.max_memory)
208 {
209 return 0;
210 }
211
212 return state->settings.mem_alloc (size, zero, state->settings.user_data);
213 }
214
new_value(json_state * state,json_value ** top,json_value ** root,json_value ** alloc,json_type type)215 static int new_value (json_state * state,
216 json_value ** top, json_value ** root, json_value ** alloc,
217 json_type type)
218 {
219 json_value * value;
220 int values_size;
221
222 if (!state->first_pass)
223 {
224 value = *top = *alloc;
225 *alloc = (*alloc)->_reserved.next_alloc;
226
227 if (!*root)
228 *root = value;
229
230 switch (value->type)
231 {
232 case json_array:
233
234 if (value->u.array.length == 0)
235 break;
236
237 if (! (value->u.array.values = (json_value **) json_alloc
238 (state, value->u.array.length * sizeof (json_value *), 0)) )
239 {
240 return 0;
241 }
242
243 value->u.array.length = 0;
244 break;
245
246 case json_object:
247
248 if (value->u.object.length == 0)
249 break;
250
251 values_size = sizeof (*value->u.object.values) * value->u.object.length;
252
253 if (! (value->u.object.values = (json_object_entry *) json_alloc
254 (state, values_size + ((unsigned long) value->u.object.values), 0)) )
255 {
256 return 0;
257 }
258
259 value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
260
261 value->u.object.length = 0;
262 break;
263
264 case json_string:
265
266 if (! (value->u.string.ptr = (json_char *) json_alloc
267 (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
268 {
269 return 0;
270 }
271
272 value->u.string.length = 0;
273 break;
274
275 default:
276 break;
277 };
278
279 return 1;
280 }
281
282 if (! (value = (json_value *) json_alloc
283 (state, sizeof (json_value) + state->settings.value_extra, 1)))
284 {
285 return 0;
286 }
287
288 if (!*root)
289 *root = value;
290
291 value->type = type;
292 value->parent = *top;
293
294 if (*alloc)
295 (*alloc)->_reserved.next_alloc = value;
296
297 *alloc = *top = value;
298
299 return 1;
300 }
301
302 #define whitespace \
303 case '\n': ++ state.cur_line; state.cur_col = 0; \
304 case ' ': case '\t': case '\r'
305
306 #define string_add(b) \
307 do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
308
309 #define line_and_col \
310 state.cur_line, state.cur_col
311
312 static const long
313 flag_next = 1 << 0,
314 flag_reproc = 1 << 1,
315 flag_need_comma = 1 << 2,
316 flag_seek_value = 1 << 3,
317 flag_escaped = 1 << 4,
318 flag_string = 1 << 5,
319 flag_need_colon = 1 << 6,
320 flag_done = 1 << 7,
321 flag_num_negative = 1 << 8,
322 flag_num_zero = 1 << 9,
323 flag_num_e = 1 << 10,
324 flag_num_e_got_sign = 1 << 11,
325 flag_num_e_negative = 1 << 12;
326
json_parse_ex(json_settings * settings,const json_char * json,size_t length,char * error_buf)327 json_value * json_parse_ex (json_settings * settings,
328 const json_char * json,
329 size_t length,
330 char * error_buf)
331 {
332 json_char error [json_error_max];
333 const json_char * end;
334 json_value * top, * root, * alloc = 0;
335 json_state state = { 0 };
336 long flags;
337 long num_digits = 0, num_e = 0;
338 json_int_t num_fraction = 0;
339
340 /* Skip UTF-8 BOM
341 */
342 if (length >= 3 && ((unsigned char) json [0]) == 0xEF
343 && ((unsigned char) json [1]) == 0xBB
344 && ((unsigned char) json [2]) == 0xBF)
345 {
346 json += 3;
347 length -= 3;
348 }
349
350 error[0] = '\0';
351 end = (json + length);
352
353 memcpy (&state.settings, settings, sizeof (json_settings));
354
355 if (!state.settings.mem_alloc)
356 state.settings.mem_alloc = default_alloc;
357
358 if (!state.settings.mem_free)
359 state.settings.mem_free = default_free;
360
361 memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
362 memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
363
364 state.uint_max -= 8; /* limit of how much can be added before next check */
365 state.ulong_max -= 8;
366
367 for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
368 {
369 json_uchar uchar;
370 unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
371 json_char * string = 0;
372 unsigned int string_length = 0;
373
374 top = root = 0;
375 flags = flag_seek_value;
376
377 state.cur_line = 1;
378
379 for (state.ptr = json ;; ++ state.ptr)
380 {
381 json_char b = (state.ptr == end ? 0 : *state.ptr);
382
383 if (flags & flag_string)
384 {
385 if (!b)
386 { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
387 goto e_failed;
388 }
389
390 if (string_length > state.uint_max)
391 goto e_overflow;
392
393 if (flags & flag_escaped)
394 {
395 flags &= ~ flag_escaped;
396
397 switch (b)
398 {
399 case 'b': string_add ('\b'); break;
400 case 'f': string_add ('\f'); break;
401 case 'n': string_add ('\n'); break;
402 case 'r': string_add ('\r'); break;
403 case 't': string_add ('\t'); break;
404 case 'u':
405
406 if (end - state.ptr <= 4 ||
407 (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
408 (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
409 (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
410 (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
411 {
412 sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
413 goto e_failed;
414 }
415
416 uc_b1 = (uc_b1 << 4) | uc_b2;
417 uc_b2 = (uc_b3 << 4) | uc_b4;
418 uchar = (uc_b1 << 8) | uc_b2;
419
420 if ((uchar & 0xF800) == 0xD800) {
421 json_uchar uchar2;
422
423 if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
424 (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
425 (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
426 (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
427 (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
428 {
429 sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
430 goto e_failed;
431 }
432
433 uc_b1 = (uc_b1 << 4) | uc_b2;
434 uc_b2 = (uc_b3 << 4) | uc_b4;
435 uchar2 = (uc_b1 << 8) | uc_b2;
436
437 uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
438 }
439
440 if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
441 {
442 string_add ((json_char) uchar);
443 break;
444 }
445
446 if (uchar <= 0x7FF)
447 {
448 if (state.first_pass)
449 string_length += 2;
450 else
451 { string [string_length ++] = 0xC0 | (uchar >> 6);
452 string [string_length ++] = 0x80 | (uchar & 0x3F);
453 }
454
455 break;
456 }
457
458 if (uchar <= 0xFFFF) {
459 if (state.first_pass)
460 string_length += 3;
461 else
462 { string [string_length ++] = 0xE0 | (uchar >> 12);
463 string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
464 string [string_length ++] = 0x80 | (uchar & 0x3F);
465 }
466
467 break;
468 }
469
470 if (state.first_pass)
471 string_length += 4;
472 else
473 { string [string_length ++] = 0xF0 | (uchar >> 18);
474 string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
475 string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
476 string [string_length ++] = 0x80 | (uchar & 0x3F);
477 }
478
479 break;
480
481 default:
482 string_add (b);
483 };
484
485 continue;
486 }
487
488 if (b == '\\')
489 {
490 flags |= flag_escaped;
491 continue;
492 }
493
494 if (b == '"')
495 {
496 if (!state.first_pass)
497 string [string_length] = 0;
498
499 flags &= ~ flag_string;
500 string = 0;
501
502 switch (top->type)
503 {
504 case json_string:
505
506 top->u.string.length = string_length;
507 flags |= flag_next;
508
509 break;
510
511 case json_object:
512
513 if (state.first_pass)
514 (*(json_char **) &top->u.object.values) += string_length + 1;
515 else
516 {
517 top->u.object.values [top->u.object.length].name
518 = (json_char *) top->_reserved.object_mem;
519
520 top->u.object.values [top->u.object.length].name_length
521 = string_length;
522
523 (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
524 }
525
526 flags |= flag_seek_value | flag_need_colon;
527 continue;
528
529 default:
530 break;
531 };
532 }
533 else
534 {
535 string_add (b);
536 continue;
537 }
538 }
539
540 if (flags & flag_done)
541 {
542 if (!b)
543 break;
544
545 switch (b)
546 {
547 whitespace:
548 continue;
549
550 default:
551
552 sprintf (error, "%d:%d: Trailing garbage: `%c`",
553 state.cur_line, state.cur_col, b);
554
555 goto e_failed;
556 };
557 }
558
559 if (flags & flag_seek_value)
560 {
561 switch (b)
562 {
563 whitespace:
564 continue;
565
566 case ']':
567
568 if (top && top->type == json_array)
569 flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
570 else
571 { sprintf (error, "%d:%d: Unexpected ]", line_and_col);
572 goto e_failed;
573 }
574
575 break;
576
577 default:
578
579 if (flags & flag_need_comma)
580 {
581 if (b == ',')
582 { flags &= ~ flag_need_comma;
583 continue;
584 }
585 else
586 {
587 sprintf (error, "%d:%d: Expected , before %c",
588 state.cur_line, state.cur_col, b);
589
590 goto e_failed;
591 }
592 }
593
594 if (flags & flag_need_colon)
595 {
596 if (b == ':')
597 { flags &= ~ flag_need_colon;
598 continue;
599 }
600 else
601 {
602 sprintf (error, "%d:%d: Expected : before %c",
603 state.cur_line, state.cur_col, b);
604
605 goto e_failed;
606 }
607 }
608
609 flags &= ~ flag_seek_value;
610
611 switch (b)
612 {
613 case '{':
614
615 if (!new_value (&state, &top, &root, &alloc, json_object))
616 goto e_alloc_failure;
617
618 continue;
619
620 case '[':
621
622 if (!new_value (&state, &top, &root, &alloc, json_array))
623 goto e_alloc_failure;
624
625 flags |= flag_seek_value;
626 continue;
627
628 case '"':
629
630 if (!new_value (&state, &top, &root, &alloc, json_string))
631 goto e_alloc_failure;
632
633 flags |= flag_string;
634
635 string = top->u.string.ptr;
636 string_length = 0;
637
638 continue;
639
640 case 't':
641
642 if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
643 *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
644 {
645 goto e_unknown_value;
646 }
647
648 if (!new_value (&state, &top, &root, &alloc, json_boolean))
649 goto e_alloc_failure;
650
651 top->u.boolean = 1;
652
653 flags |= flag_next;
654 break;
655
656 case 'f':
657
658 if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
659 *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
660 *(++ state.ptr) != 'e')
661 {
662 goto e_unknown_value;
663 }
664
665 if (!new_value (&state, &top, &root, &alloc, json_boolean))
666 goto e_alloc_failure;
667
668 flags |= flag_next;
669 break;
670
671 case 'n':
672
673 if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
674 *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
675 {
676 goto e_unknown_value;
677 }
678
679 if (!new_value (&state, &top, &root, &alloc, json_null))
680 goto e_alloc_failure;
681
682 flags |= flag_next;
683 break;
684
685 default:
686
687 if (isdigit (b) || b == '-')
688 {
689 if (!new_value (&state, &top, &root, &alloc, json_integer))
690 goto e_alloc_failure;
691
692 if (!state.first_pass)
693 {
694 while (isdigit (b) || b == '+' || b == '-'
695 || b == 'e' || b == 'E' || b == '.')
696 {
697 if ( (++ state.ptr) == end)
698 {
699 b = 0;
700 break;
701 }
702
703 b = *state.ptr;
704 }
705
706 flags |= flag_next | flag_reproc;
707 break;
708 }
709
710 flags &= ~ (flag_num_negative | flag_num_e |
711 flag_num_e_got_sign | flag_num_e_negative |
712 flag_num_zero);
713
714 num_digits = 0;
715 num_fraction = 0;
716 num_e = 0;
717
718 if (b != '-')
719 {
720 flags |= flag_reproc;
721 break;
722 }
723
724 flags |= flag_num_negative;
725 continue;
726 }
727 else
728 { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
729 goto e_failed;
730 }
731 };
732 };
733 }
734 else
735 {
736 switch (top->type)
737 {
738 case json_object:
739
740 switch (b)
741 {
742 whitespace:
743 continue;
744
745 case '"':
746
747 if (flags & flag_need_comma)
748 { sprintf (error, "%d:%d: Expected , before \"", line_and_col);
749 goto e_failed;
750 }
751
752 flags |= flag_string;
753
754 string = (json_char *) top->_reserved.object_mem;
755 string_length = 0;
756
757 break;
758
759 case '}':
760
761 flags = (flags & ~ flag_need_comma) | flag_next;
762 break;
763
764 case ',':
765
766 if (flags & flag_need_comma)
767 {
768 flags &= ~ flag_need_comma;
769 break;
770 }
771
772 default:
773 sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
774 goto e_failed;
775 };
776
777 break;
778
779 case json_integer:
780 case json_double:
781
782 if (isdigit (b))
783 {
784 ++ num_digits;
785
786 if (top->type == json_integer || flags & flag_num_e)
787 {
788 if (! (flags & flag_num_e))
789 {
790 if (flags & flag_num_zero)
791 { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
792 goto e_failed;
793 }
794
795 if (num_digits == 1 && b == '0')
796 flags |= flag_num_zero;
797 }
798 else
799 {
800 flags |= flag_num_e_got_sign;
801 num_e = (num_e * 10) + (b - '0');
802 continue;
803 }
804
805 top->u.integer = (top->u.integer * 10) + (b - '0');
806 continue;
807 }
808
809 num_fraction = (num_fraction * 10) + (b - '0');
810 continue;
811 }
812
813 if (b == '+' || b == '-')
814 {
815 if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
816 {
817 flags |= flag_num_e_got_sign;
818
819 if (b == '-')
820 flags |= flag_num_e_negative;
821
822 continue;
823 }
824 }
825 else if (b == '.' && top->type == json_integer)
826 {
827 if (!num_digits)
828 { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
829 goto e_failed;
830 }
831
832 top->type = json_double;
833 top->u.dbl = (double) top->u.integer;
834
835 num_digits = 0;
836 continue;
837 }
838
839 if (flags & flag_num_negative)
840 {
841 if (top->type == json_integer)
842 top->u.integer = - top->u.integer;
843 else
844 top->u.dbl = - top->u.dbl;
845 }
846
847 flags |= flag_next | flag_reproc;
848 break;
849
850 default:
851 break;
852 };
853 }
854
855 if (flags & flag_reproc)
856 {
857 flags &= ~ flag_reproc;
858 -- state.ptr;
859 }
860
861 if (flags & flag_next)
862 {
863 flags = (flags & ~ flag_next) | flag_need_comma;
864
865 if (!top->parent)
866 {
867 /* root value done */
868
869 flags |= flag_done;
870 continue;
871 }
872
873 if (top->parent->type == json_array)
874 flags |= flag_seek_value;
875
876 if (!state.first_pass)
877 {
878 json_value * parent = top->parent;
879
880 switch (parent->type)
881 {
882 case json_object:
883
884 parent->u.object.values
885 [parent->u.object.length].value = top;
886
887 break;
888
889 case json_array:
890
891 parent->u.array.values
892 [parent->u.array.length] = top;
893
894 break;
895
896 default:
897 break;
898 };
899 }
900
901 if ( (++ top->parent->u.array.length) > state.uint_max)
902 goto e_overflow;
903
904 top = top->parent;
905
906 continue;
907 }
908 }
909
910 alloc = root;
911 }
912
913 return root;
914
915 e_unknown_value:
916
917 sprintf (error, "%d:%d: Unknown value", line_and_col);
918 goto e_failed;
919
920 e_alloc_failure:
921
922 strcpy (error, "Memory allocation failure");
923 goto e_failed;
924
925 e_overflow:
926
927 sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
928 goto e_failed;
929
930 e_failed:
931
932 if (error_buf)
933 {
934 if (*error)
935 strcpy (error_buf, error);
936 else
937 strcpy (error_buf, "Unknown error");
938 }
939
940 if (state.first_pass)
941 alloc = root;
942
943 while (alloc)
944 {
945 top = alloc->_reserved.next_alloc;
946 state.settings.mem_free (alloc, state.settings.user_data);
947 alloc = top;
948 }
949
950 if (!state.first_pass)
951 json_value_free_ex (&state.settings, root);
952
953 return 0;
954 }
955
json_parse(const json_char * json,size_t length)956 json_value * json_parse (const json_char * json, size_t length)
957 {
958 json_settings settings = { 0 };
959 return json_parse_ex (&settings, json, length, 0);
960 }
961
json_value_free_ex(json_settings * settings,json_value * value)962 void json_value_free_ex (json_settings * settings, json_value * value)
963 {
964 json_value * cur_value;
965
966 if (!value)
967 return;
968
969 value->parent = 0;
970
971 while (value)
972 {
973 switch (value->type)
974 {
975 case json_array:
976
977 if (!value->u.array.length)
978 {
979 settings->mem_free (value->u.array.values, settings->user_data);
980 break;
981 }
982
983 value = value->u.array.values [-- value->u.array.length];
984 continue;
985
986 case json_object:
987
988 if (!value->u.object.length)
989 {
990 settings->mem_free (value->u.object.values, settings->user_data);
991 break;
992 }
993
994 value = value->u.object.values [-- value->u.object.length].value;
995 continue;
996
997 case json_string:
998
999 settings->mem_free (value->u.string.ptr, settings->user_data);
1000 break;
1001
1002 default:
1003 break;
1004 };
1005
1006 cur_value = value;
1007 value = value->parent;
1008 settings->mem_free (cur_value, settings->user_data);
1009 }
1010 }
1011
1012 #define BUFSIZE 10000000
1013
main(int argc,char * argv[])1014 int main(int argc, char *argv[])
1015 {
1016 if (argc != 3) {
1017 printf("Usage: parse-compile-commands <path-to-compile_commands.json> <source-file>\n");
1018 return -1;
1019 }
1020 else {
1021 char *buf = malloc(BUFSIZE);
1022 FILE *file = fopen(argv[1], "r");
1023 if (!file) {
1024 return -1;
1025 }
1026 else {
1027 size_t len = fread(buf, 1, BUFSIZE, file);
1028 fclose(file);
1029
1030 if (len > 0) {
1031 json_value *val = json_parse(buf, len);
1032 if (val) {
1033 unsigned i = 0;
1034 for (i = 0; i < val->u.array.length; ++i) {
1035 json_value *object = val->u.array.values[i];
1036 char *command = NULL;
1037 char *source = NULL;
1038 unsigned j = 0;
1039 for (j = 0; j < object->u.object.length; ++j) {
1040 if (!strcmp(object->u.object.values[j].name, "file")) {
1041 source = object->u.object.values[j].value->u.string.ptr;
1042 }
1043 else if (!strcmp(object->u.object.values[j].name, "command")) {
1044 command = object->u.object.values[j].value->u.string.ptr;
1045 }
1046 }
1047
1048 if (!strcmp(source, argv[2])) {
1049 printf("%s\n", command);
1050 return 0;
1051 }
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058 return -1;
1059 }
1060