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