source: lib/json.c @ b4b8f1e

Last change on this file since b4b8f1e was b4b8f1e, checked in by Wilmer van der Gaast <wilmer@…>, at 2014-03-02T00:37:43Z

Unicode parsing fix in JSON parser: JSON can contain UTF-16 surrogate pairs
(used to encode >16-bit chars). Added code to parse those *and* the ability
to encode >16-bit Unicode in UTF-8. Also sending this upstream. This should
fix #1121.

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