1 /* vim: set et ts=3 sw=3 ft=c:
3 * Copyright (C) 2012 James McLaughlin et al. All rights reserved.
4 * https://github.com/udp/json-parser
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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
33 #ifndef _CRT_SECURE_NO_WARNINGS
34 #define _CRT_SECURE_NO_WARNINGS
39 const struct _json_value json_value_none
; /* zero-d by ctor */
41 const struct _json_value json_value_none
= { 0, 0, { 0 }, { 0 } };
50 typedef unsigned short json_uchar
;
52 static unsigned char hex_value (json_char c
)
54 if (c
>= 'A' && c
<= 'F')
55 return (c
- 'A') + 10;
57 if (c
>= 'a' && c
<= 'f')
58 return (c
- 'a') + 10;
60 if (c
>= '0' && c
<= '9')
68 json_settings settings
;
71 unsigned long used_memory
;
73 unsigned int uint_max
;
74 unsigned long ulong_max
;
78 static void * json_alloc (json_state
* state
, unsigned long size
, int zero
)
82 if ((state
->ulong_max
- state
->used_memory
) < size
)
85 if (state
->settings
.max_memory
86 && (state
->used_memory
+= size
) > state
->settings
.max_memory
)
91 if (! (mem
= zero
? calloc (size
, 1) : malloc (size
)))
98 (json_state
* state
, json_value
** top
, json_value
** root
, json_value
** alloc
, json_type type
)
103 if (!state
->first_pass
)
105 value
= *top
= *alloc
;
106 *alloc
= (*alloc
)->_reserved
.next_alloc
;
115 if (! (value
->u
.array
.values
= (json_value
**) json_alloc
116 (state
, value
->u
.array
.length
* sizeof (json_value
*), 0)) )
121 value
->u
.array
.length
= 0;
126 values_size
= sizeof (*value
->u
.object
.values
) * value
->u
.object
.length
;
128 if (! ((*(void **) &value
->u
.object
.values
) = json_alloc
129 (state
, values_size
+ ((unsigned long) value
->u
.object
.values
), 0)) )
134 value
->_reserved
.object_mem
= (*(char **) &value
->u
.object
.values
) + values_size
;
136 value
->u
.object
.length
= 0;
141 if (! (value
->u
.string
.ptr
= (json_char
*) json_alloc
142 (state
, (value
->u
.string
.length
+ 1) * sizeof (json_char
), 0)) )
147 value
->u
.string
.length
= 0;
157 value
= (json_value
*) json_alloc (state
, sizeof (json_value
), 1);
166 value
->parent
= *top
;
169 (*alloc
)->_reserved
.next_alloc
= value
;
171 *alloc
= *top
= value
;
177 ((int) (i - cur_line_begin))
180 case '\n': ++ cur_line; cur_line_begin = i; \
182 case ' ': case '\t': case '\r'
184 #define string_add(b) \
185 do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
188 flag_next
= 1, flag_reproc
= 2, flag_need_comma
= 4, flag_seek_value
= 8,
189 flag_escaped
= 16, flag_string
= 32, flag_need_colon
= 64, flag_done
= 128,
190 flag_num_negative
= 256, flag_num_zero
= 512, flag_num_e
= 1024,
191 flag_num_e_got_sign
= 2048, flag_num_e_negative
= 4096;
193 json_value
* json_parse_ex (json_settings
* settings
, const json_char
* json
, char * error_buf
)
195 json_char error
[128];
196 unsigned int cur_line
;
197 const json_char
* cur_line_begin
, * i
;
198 json_value
* top
, * root
, * alloc
= 0;
201 long num_digits
= 0, num_fraction
= 0, num_e
= 0;
205 memset (&state
, 0, sizeof (json_state
));
206 memcpy (&state
.settings
, settings
, sizeof (json_settings
));
208 memset (&state
.uint_max
, 0xFF, sizeof (state
.uint_max
));
209 memset (&state
.ulong_max
, 0xFF, sizeof (state
.ulong_max
));
211 state
.uint_max
-= 8; /* limit of how much can be added before next check */
212 state
.ulong_max
-= 8;
214 for (state
.first_pass
= 1; state
.first_pass
>= 0; -- state
.first_pass
)
217 unsigned char uc_b1
, uc_b2
, uc_b3
, uc_b4
;
218 json_char
* string
= NULL
;
219 unsigned int string_length
= 0;
222 flags
= flag_seek_value
;
225 cur_line_begin
= json
;
227 for (i
= json
;; ++ i
)
231 if (flags
& flag_done
)
242 sprintf (error
, "%d:%d: Trailing garbage: `%c`", cur_line
, e_off
, b
);
247 if (flags
& flag_string
)
250 { sprintf (error
, "Unexpected EOF in string (at %d:%d)", cur_line
, e_off
);
254 if (string_length
> state
.uint_max
)
257 if (flags
& flag_escaped
)
259 flags
&= ~ flag_escaped
;
263 case 'b': string_add ('\b'); break;
264 case 'f': string_add ('\f'); break;
265 case 'n': string_add ('\n'); break;
266 case 'r': string_add ('\r'); break;
267 case 't': string_add ('\t'); break;
270 if ((uc_b1
= hex_value (*++ i
)) == 0xFF || (uc_b2
= hex_value (*++ i
)) == 0xFF
271 || (uc_b3
= hex_value (*++ i
)) == 0xFF || (uc_b4
= hex_value (*++ i
)) == 0xFF)
273 sprintf (error
, "Invalid character value `%c` (at %d:%d)", b
, cur_line
, e_off
);
277 uc_b1
= uc_b1
* 16 + uc_b2
;
278 uc_b2
= uc_b3
* 16 + uc_b4
;
280 uchar
= ((json_char
) uc_b1
) * 256 + uc_b2
;
282 if (sizeof (json_char
) >= sizeof (json_uchar
) || (uc_b1
== 0 && uc_b2
<= 0x7F))
284 string_add ((json_char
) uchar
);
290 if (state
.first_pass
)
293 { string
[string_length
++] = 0xC0 | ((uc_b2
& 0xC0) >> 6) | ((uc_b1
& 0x7) << 2);
294 string
[string_length
++] = 0x80 | (uc_b2
& 0x3F);
300 if (state
.first_pass
)
303 { string
[string_length
++] = 0xE0 | ((uc_b1
& 0xF0) >> 4);
304 string
[string_length
++] = 0x80 | ((uc_b1
& 0xF) << 2) | ((uc_b2
& 0xC0) >> 6);
305 string
[string_length
++] = 0x80 | (uc_b2
& 0x3F);
319 flags
|= flag_escaped
;
325 if (!state
.first_pass
)
326 string
[string_length
] = 0;
328 flags
&= ~ flag_string
;
335 top
->u
.string
.length
= string_length
;
342 if (state
.first_pass
)
343 (*(json_char
**) &top
->u
.object
.values
) += string_length
+ 1;
346 top
->u
.object
.values
[top
->u
.object
.length
].name
347 = (json_char
*) top
->_reserved
.object_mem
;
349 (*(json_char
**) &top
->_reserved
.object_mem
) += string_length
+ 1;
352 flags
|= flag_seek_value
| flag_need_colon
;
366 if (flags
& flag_seek_value
)
375 if (top
->type
== json_array
)
376 flags
= (flags
& ~ (flag_need_comma
| flag_seek_value
)) | flag_next
;
377 else if (!state
.settings
.settings
& json_relaxed_commas
)
378 { sprintf (error
, "%d:%d: Unexpected ]", cur_line
, e_off
);
386 if (flags
& flag_need_comma
)
389 { flags
&= ~ flag_need_comma
;
393 { sprintf (error
, "%d:%d: Expected , before %c", cur_line
, e_off
, b
);
398 if (flags
& flag_need_colon
)
401 { flags
&= ~ flag_need_colon
;
405 { sprintf (error
, "%d:%d: Expected : before %c", cur_line
, e_off
, b
);
410 flags
&= ~ flag_seek_value
;
416 if (!new_value (&state
, &top
, &root
, &alloc
, json_object
))
417 goto e_alloc_failure
;
423 if (!new_value (&state
, &top
, &root
, &alloc
, json_array
))
424 goto e_alloc_failure
;
426 flags
|= flag_seek_value
;
431 if (!new_value (&state
, &top
, &root
, &alloc
, json_string
))
432 goto e_alloc_failure
;
434 flags
|= flag_string
;
436 string
= top
->u
.string
.ptr
;
443 if (*(++ i
) != 'r' || *(++ i
) != 'u' || *(++ i
) != 'e')
444 goto e_unknown_value
;
446 if (!new_value (&state
, &top
, &root
, &alloc
, json_boolean
))
447 goto e_alloc_failure
;
456 if (*(++ i
) != 'a' || *(++ i
) != 'l' || *(++ i
) != 's' || *(++ i
) != 'e')
457 goto e_unknown_value
;
459 if (!new_value (&state
, &top
, &root
, &alloc
, json_boolean
))
460 goto e_alloc_failure
;
467 if (*(++ i
) != 'u' || *(++ i
) != 'l' || *(++ i
) != 'l')
468 goto e_unknown_value
;
470 if (!new_value (&state
, &top
, &root
, &alloc
, json_null
))
471 goto e_alloc_failure
;
478 if (isdigit (b
) || b
== '-')
480 if (!new_value (&state
, &top
, &root
, &alloc
, json_integer
))
481 goto e_alloc_failure
;
483 if (!state
.first_pass
)
485 while (isdigit (b
) || b
== '+' || b
== '-'
486 || b
== 'e' || b
== 'E' || b
== '.')
491 flags
|= flag_next
| flag_reproc
;
495 flags
&= ~ (flag_num_negative
| flag_num_e
|
496 flag_num_e_got_sign
| flag_num_e_negative
|
505 flags
|= flag_reproc
;
509 flags
|= flag_num_negative
;
513 { sprintf (error
, "%d:%d: Unexpected %c when seeking value", cur_line
, e_off
, b
);
532 if (flags
& flag_need_comma
&& (!state
.settings
.settings
& json_relaxed_commas
))
534 sprintf (error
, "%d:%d: Expected , before \"", cur_line
, e_off
);
538 flags
|= flag_string
;
540 string
= (json_char
*) top
->_reserved
.object_mem
;
547 flags
= (flags
& ~ flag_need_comma
) | flag_next
;
552 if (flags
& flag_need_comma
)
554 flags
&= ~ flag_need_comma
;
561 sprintf (error
, "%d:%d: Unexpected `%c` in object", cur_line
, e_off
, b
);
574 if (top
->type
== json_integer
|| flags
& flag_num_e
)
576 if (! (flags
& flag_num_e
))
578 if (flags
& flag_num_zero
)
579 { sprintf (error
, "%d:%d: Unexpected `0` before `%c`", cur_line
, e_off
, b
);
583 if (num_digits
== 1 && b
== '0')
584 flags
|= flag_num_zero
;
588 flags
|= flag_num_e_got_sign
;
589 num_e
= (num_e
* 10) + (b
- '0');
593 top
->u
.integer
= (top
->u
.integer
* 10) + (b
- '0');
597 num_fraction
= (num_fraction
* 10) + (b
- '0');
601 if (b
== '+' || b
== '-')
603 if ( (flags
& flag_num_e
) && !(flags
& flag_num_e_got_sign
))
605 flags
|= flag_num_e_got_sign
;
608 flags
|= flag_num_e_negative
;
613 else if (b
== '.' && top
->type
== json_integer
)
616 { sprintf (error
, "%d:%d: Expected digit before `.`", cur_line
, e_off
);
620 top
->type
= json_double
;
621 top
->u
.dbl
= (double) top
->u
.integer
;
627 if (! (flags
& flag_num_e
))
629 if (top
->type
== json_double
)
632 { sprintf (error
, "%d:%d: Expected digit after `.`", cur_line
, e_off
);
636 top
->u
.dbl
+= ((double) num_fraction
) / (pow ( (double) 10.0, (double) num_digits
));
639 if (b
== 'e' || b
== 'E')
643 if (top
->type
== json_integer
)
645 top
->type
= json_double
;
646 top
->u
.dbl
= (double) top
->u
.integer
;
650 flags
&= ~ flag_num_zero
;
658 { sprintf (error
, "%d:%d: Expected digit after `e`", cur_line
, e_off
);
662 top
->u
.dbl
*= pow (10, (double) (flags
& flag_num_e_negative
? - num_e
: num_e
));
665 if (flags
& flag_num_negative
)
667 if (top
->type
== json_integer
)
668 top
->u
.integer
= - top
->u
.integer
;
670 top
->u
.dbl
= - top
->u
.dbl
;
673 flags
|= flag_next
| flag_reproc
;
681 if (flags
& flag_reproc
)
683 flags
&= ~ flag_reproc
;
687 if (flags
& flag_next
)
689 flags
= (flags
& ~ flag_next
) | flag_need_comma
;
693 /* root value done */
699 if (top
->parent
->type
== json_array
)
700 flags
|= flag_seek_value
;
702 if (!state
.first_pass
)
704 json_value
* parent
= top
->parent
;
706 switch (parent
->type
)
710 parent
->u
.object
.values
711 [parent
->u
.object
.length
].value
= top
;
717 parent
->u
.array
.values
718 [parent
->u
.array
.length
] = top
;
727 if ( (++ top
->parent
->u
.array
.length
) > state
.uint_max
)
743 sprintf (error
, "%d:%d: Unknown value", cur_line
, e_off
);
748 strcpy (error
, "Memory allocation failure");
753 sprintf (error
, "%d:%d: Too long (caught overflow)", cur_line
, e_off
);
761 strcpy (error_buf
, error
);
763 strcpy (error_buf
, "Unknown error");
766 if (state
.first_pass
)
771 top
= alloc
->_reserved
.next_alloc
;
776 if (!state
.first_pass
)
777 json_value_free (root
);
782 json_value
* json_parse (const json_char
* json
)
784 json_settings settings
;
785 memset (&settings
, 0, sizeof (json_settings
));
787 return json_parse_ex (&settings
, json
, 0);
790 void json_value_free (json_value
* value
)
792 json_value
* cur_value
;
805 if (!value
->u
.array
.length
)
807 free (value
->u
.array
.values
);
811 value
= value
->u
.array
.values
[-- value
->u
.array
.length
];
816 if (!value
->u
.object
.length
)
818 free (value
->u
.object
.values
);
822 value
= value
->u
.object
.values
[-- value
->u
.object
.length
].value
;
827 free (value
->u
.string
.ptr
);
835 value
= value
->parent
;