Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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