source: trunk/libtransmission/JSON_parser.c @ 5869

Last change on this file since 5869 was 5869, checked in by charles, 14 years ago

(rpc) refresh our snapshot of Jean Gressmann's JSON parser

File size: 29.2 KB
Line 
1/* JSON_parser.c */
2
3/* 2007-08-24 */
4
5/*
6Copyright (c) 2005 JSON.org
7
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in all
16copies or substantial portions of the Software.
17
18The Software shall be used for Good, not Evil.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27*/
28
29/*
30    Callbacks, comments, Unicode handling by Jean Gressmann (jean@0x42.de), 2007-2008.
31   
32    For the added features the license above applies also.
33*/
34
35
36
37#include <assert.h>
38#include <ctype.h>
39#include <float.h>
40#include <stddef.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#include "JSON_parser.h"
46#include "ConvertUTF.h"
47
48#if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
49#       pragma warning(disable:4996) // unsecure sscanf
50#endif
51
52
53#define true  1
54#define false 0
55#define __   -1     /* the universal error code */
56
57/* values chosen so that the object approx. fits into a page (4K) */
58#ifndef JSON_PARSER_STACK_SIZE
59#   define JSON_PARSER_STACK_SIZE 128
60#endif
61
62#ifndef JSON_PARSER_PARSE_BUFFER_SIZE
63#   define JSON_PARSER_PARSE_BUFFER_SIZE 3500
64#endif
65
66
67typedef struct JSON_parser_struct {
68    JSON_parser_callback callback;
69    void* ctx;
70    signed char state, before_comment_state, type, escaped, comment, allow_comments, handle_floats_manually;
71    UTF16 utf16_decode_buffer[2];
72    long depth;
73    long top;
74    signed char* stack;
75    long stack_capacity;
76    signed char static_stack[JSON_PARSER_STACK_SIZE];
77    char* parse_buffer;
78    size_t parse_buffer_capacity;
79    size_t parse_buffer_count;
80    size_t comment_begin_offset;
81    char static_parse_buffer[JSON_PARSER_PARSE_BUFFER_SIZE];
82} * JSON_parser;
83
84#define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
85
86/*
87    Characters are mapped into these 31 character classes. This allows for
88    a significant reduction in the size of the state transition table.
89*/
90
91
92
93enum classes {
94    C_SPACE,  /* space */
95    C_WHITE,  /* other whitespace */
96    C_LCURB,  /* {  */
97    C_RCURB,  /* } */
98    C_LSQRB,  /* [ */
99    C_RSQRB,  /* ] */
100    C_COLON,  /* : */
101    C_COMMA,  /* , */
102    C_QUOTE,  /* " */
103    C_BACKS,  /* \ */
104    C_SLASH,  /* / */
105    C_PLUS,   /* + */
106    C_MINUS,  /* - */
107    C_POINT,  /* . */
108    C_ZERO ,  /* 0 */
109    C_DIGIT,  /* 123456789 */
110    C_LOW_A,  /* a */
111    C_LOW_B,  /* b */
112    C_LOW_C,  /* c */
113    C_LOW_D,  /* d */
114    C_LOW_E,  /* e */
115    C_LOW_F,  /* f */
116    C_LOW_L,  /* l */
117    C_LOW_N,  /* n */
118    C_LOW_R,  /* r */
119    C_LOW_S,  /* s */
120    C_LOW_T,  /* t */
121    C_LOW_U,  /* u */
122    C_ABCDF,  /* ABCDF */
123    C_E,      /* E */
124    C_ETC,    /* everything else */
125    C_STAR,   /* * */   
126    NR_CLASSES
127};
128
129static int ascii_class[128] = {
130/*
131    This array maps the 128 ASCII characters into character classes.
132    The remaining Unicode characters should be mapped to C_ETC.
133    Non-whitespace control characters are errors.
134*/
135    __,      __,      __,      __,      __,      __,      __,      __,
136    __,      C_WHITE, C_WHITE, __,      __,      C_WHITE, __,      __,
137    __,      __,      __,      __,      __,      __,      __,      __,
138    __,      __,      __,      __,      __,      __,      __,      __,
139
140    C_SPACE, C_ETC,   C_QUOTE, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
141    C_ETC,   C_ETC,   C_STAR,   C_PLUS,  C_COMMA, C_MINUS, C_POINT, C_SLASH,
142    C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
143    C_DIGIT, C_DIGIT, C_COLON, C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
144
145    C_ETC,   C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_ETC,
146    C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
147    C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_ETC,
148    C_ETC,   C_ETC,   C_ETC,   C_LSQRB, C_BACKS, C_RSQRB, C_ETC,   C_ETC,
149
150    C_ETC,   C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
151    C_ETC,   C_ETC,   C_ETC,   C_ETC,   C_LOW_L, C_ETC,   C_LOW_N, C_ETC,
152    C_ETC,   C_ETC,   C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC,   C_ETC,
153    C_ETC,   C_ETC,   C_ETC,   C_LCURB, C_ETC,   C_RCURB, C_ETC,   C_ETC
154};
155
156
157/*
158    The state codes.
159*/
160enum states {
161    GO,  /* start    */
162    OK,  /* ok       */
163    OB,  /* object   */
164    KE,  /* key      */
165    CO,  /* colon    */
166    VA,  /* value    */
167    AR,  /* array    */
168    ST,  /* string   */
169    ES,  /* escape   */
170    U1,  /* u1       */
171    U2,  /* u2       */
172    U3,  /* u3       */
173    U4,  /* u4       */
174    MI,  /* minus    */
175    ZE,  /* zero     */
176    IN,  /* integer  */
177    FR,  /* fraction */
178    E1,  /* e        */
179    E2,  /* ex       */
180    E3,  /* exp      */
181    T1,  /* tr       */
182    T2,  /* tru      */
183    T3,  /* true     */
184    F1,  /* fa       */
185    F2,  /* fal      */
186    F3,  /* fals     */
187    F4,  /* false    */
188    N1,  /* nu       */
189    N2,  /* nul      */
190    N3,  /* null     */
191    C1,  /* /        */
192    C2,  /* / *     */
193    C3,  /* *        */
194    FX,  /* *.* *eE* */
195    D1,  /* second UTF-16 character decoding started by \ */
196    D2,  /* second UTF-16 character proceeded by u */
197    NR_STATES
198};
199
200enum actions
201{
202    CB = -10, /* comment begin */
203    CE = -11, /* comment end */
204    FA = -12, /* false */
205    TR = -13, /* false */
206    NU = -14, /* null */
207    DE = -15, /* double detected by exponent e E */
208    DF = -16, /* double detected by fraction . */
209    SB = -17, /* string begin */
210    MX = -18, /* integer detected by minus */
211    ZX = -19, /* integer detected by zero */
212    IX = -20, /* integer detected by 1-9 */
213    EX = -21, /* next char is escaped */
214    UC = -22, /* Unicode character read */
215};
216
217
218static int state_transition_table[NR_STATES][NR_CLASSES] = {
219/*
220    The state transition table takes the current state and the current symbol,
221    and returns either a new state or an action. An action is represented as a
222    negative number. A JSON text is accepted if at the end of the text the
223    state is OK and if the mode is MODE_DONE.
224
225                 white                                      1-9                                   ABCDF  etc
226             space |  {  }  [  ]  :  ,  "  \  /  +  -  .  0  |  a  b  c  d  e  f  l  n  r  s  t  u  |  E  |  * */
227/*start  GO*/ {GO,GO,-6,__,-5,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
228/*ok     OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
229/*object OB*/ {OB,OB,__,-9,__,__,__,__,SB,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
230/*key    KE*/ {KE,KE,__,__,__,__,__,__,SB,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
231/*colon  CO*/ {CO,CO,__,__,__,__,-2,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
232/*value  VA*/ {VA,VA,-6,__,-5,__,__,__,SB,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,FA,__,NU,__,__,TR,__,__,__,__,__},
233/*array  AR*/ {AR,AR,-6,__,-5,-7,__,__,SB,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,FA,__,NU,__,__,TR,__,__,__,__,__},
234/*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,EX,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
235/*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__,__},
236/*u1     U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__,__},
237/*u2     U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__,__},
238/*u3     U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__,__},
239/*u4     U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,UC,UC,UC,UC,UC,UC,UC,UC,__,__,__,__,__,__,UC,UC,__,__},
240/*minus  MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
241/*zero   ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,DF,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
242/*int    IN*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,DF,IN,IN,__,__,__,__,DE,__,__,__,__,__,__,__,__,DE,__,__},
243/*frac   FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__,__},
244/*e      E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
245/*ex     E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
246/*exp    E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
247/*tr     T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__,__},
248/*tru    T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__,__},
249/*true   T3*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__},
250/*fa     F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
251/*fal    F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__,__},
252/*fals   F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__,__},
253/*false  F4*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__},
254/*nu     N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__,__},
255/*nul    N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__,__},
256/*null   N3*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__},
257/*/      C1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,C2},
258/*/*     C2*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3},
259/**      C3*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,CE,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3},
260/*_.     FX*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__,__},
261/*\      D1*/ {__,__,__,__,__,__,__,__,__,D2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
262/*\      D2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U1,__,__,__,__},
263};
264
265
266/*
267    These modes can be pushed on the stack.
268*/
269enum modes {
270    MODE_ARRAY = 1, 
271    MODE_DONE = 2, 
272    MODE_KEY = 3,   
273    MODE_OBJECT = 4
274};
275
276static int
277push(JSON_parser jc, int mode)
278{
279/*
280    Push a mode onto the stack. Return false if there is overflow.
281*/
282    jc->top += 1;
283    if (jc->depth < 0) {
284        if (jc->top >= jc->stack_capacity) {
285            jc->stack_capacity *= 2;
286            if (jc->stack == &jc->static_stack[0]) {
287                jc->stack = (signed char*)malloc(jc->stack_capacity * sizeof(jc->static_stack[0]));
288                memcpy(jc->stack, jc->static_stack, sizeof(jc->static_stack));
289            } else {
290                jc->stack = (signed char*)realloc(jc->stack, jc->stack_capacity * sizeof(jc->static_stack[0]));
291            }
292        }
293    } else {
294        if (jc->top >= jc->depth) {
295            return false;
296        }
297    }
298   
299    jc->stack[jc->top] = mode;
300    return true;
301}
302
303
304static int
305pop(JSON_parser jc, int mode)
306{
307/*
308    Pop the stack, assuring that the current mode matches the expectation.
309    Return false if there is underflow or if the modes mismatch.
310*/
311    if (jc->top < 0 || jc->stack[jc->top] != mode) {
312        return false;
313    }
314    jc->top -= 1;
315    return true;
316}
317
318
319#define parse_buffer_clear(jc) \
320    do {\
321        jc->parse_buffer_count = 0;\
322        jc->parse_buffer[0] = 0;\
323    } while (0)
324   
325#define parse_buffer_pop_back_char(jc)\
326    do {\
327        assert(jc->parse_buffer_count >= 1);\
328        --jc->parse_buffer_count;\
329        jc->parse_buffer[jc->parse_buffer_count] = 0;\
330    } while (0)   
331   
332void delete_JSON_parser(JSON_parser jc)
333{
334    if (jc) {
335        if (jc->stack != &jc->static_stack[0]) {
336            free((void*)jc->stack);
337        }
338        if (jc->parse_buffer != &jc->static_parse_buffer[0]) {
339            free((void*)jc->parse_buffer);
340        }
341        free((void*)jc);
342     }   
343}
344
345
346JSON_parser
347new_JSON_parser(JSON_config* config)
348{
349/*
350    new_JSON_parser starts the checking process by constructing a JSON_parser
351    object. It takes a depth parameter that restricts the level of maximum
352    nesting.
353
354    To continue the process, call JSON_parser_char for each character in the
355    JSON text, and then call JSON_parser_done to obtain the final result.
356    These functions are fully reentrant.
357*/
358
359    int depth = 0;
360    JSON_config default_config;
361   
362    JSON_parser jc = malloc(sizeof(struct JSON_parser_struct));
363   
364    memset(jc, 0, sizeof(*jc));
365   
366   
367    /* initialize configuration */
368    init_JSON_config(&default_config);
369   
370    /* set to default configuration if none was provided */
371    if (config == NULL) {
372        config = &default_config;
373    }
374
375    depth = config->depth;
376   
377    /* We need to be able to push at least one object */
378    if (depth == 0) {
379        depth = 1;
380    }
381   
382    jc->state = GO;
383    jc->top = -1;
384   
385    /* Do we want non-bound stack? */
386    if (depth > 0) {
387        jc->stack_capacity = depth;
388        jc->depth = depth;
389        if (depth <= (int)COUNTOF(jc->static_stack)) {
390            jc->stack = &jc->static_stack[0];
391        } else {
392            jc->stack = (signed char*)malloc(jc->stack_capacity * sizeof(jc->static_stack[0]));
393        }
394    } else {
395        jc->stack_capacity = COUNTOF(jc->static_stack);
396        jc->depth = -1;
397        jc->stack = &jc->static_stack[0];
398    }
399   
400    /* set parser to start */
401    push(jc, MODE_DONE);
402   
403    /* set up the parse buffer */
404    jc->parse_buffer = &jc->static_parse_buffer[0];
405    jc->parse_buffer_capacity = COUNTOF(jc->static_parse_buffer);
406    parse_buffer_clear(jc);
407   
408    /* set up callback, comment & float handling */
409    jc->callback = config->callback;
410    jc->ctx = config->callback_ctx;
411    jc->allow_comments = config->allow_comments != 0;
412    jc->handle_floats_manually = config->handle_floats_manually != 0;
413    return jc;
414}
415
416static void grow_parse_buffer(JSON_parser jc)
417{
418    jc->parse_buffer_capacity *= 2;
419    if (jc->parse_buffer == &jc->static_parse_buffer[0]) {
420        jc->parse_buffer = (char*)malloc(jc->parse_buffer_capacity * sizeof(jc->parse_buffer[0]));
421        memcpy(jc->parse_buffer, jc->static_parse_buffer, jc->parse_buffer_count);
422    } else {
423        jc->parse_buffer = (char*)realloc(jc->parse_buffer, jc->parse_buffer_capacity * sizeof(jc->parse_buffer[0]));
424    }
425}
426
427#define parse_buffer_push_back_char(jc, c)\
428    do {\
429        if (jc->parse_buffer_count + 1 >= jc->parse_buffer_capacity) grow_parse_buffer(jc);\
430        jc->parse_buffer[jc->parse_buffer_count++] = c;\
431        jc->parse_buffer[jc->parse_buffer_count] = 0;\
432    } while (0)
433
434
435static int parse_parse_buffer(JSON_parser jc)
436{
437    if (jc->callback) {
438        int result = 1;
439        JSON_value value, *arg = NULL;
440       
441        if (jc->type != JSON_T_NONE) {
442            assert(
443                jc->type == JSON_T_NULL ||
444                jc->type == JSON_T_FALSE ||
445                jc->type == JSON_T_TRUE ||
446                jc->type == JSON_T_FLOAT ||
447                jc->type == JSON_T_INTEGER ||
448                jc->type == JSON_T_STRING);
449               
450       
451            switch(jc->type) {
452                case JSON_T_FLOAT:
453                    arg = &value;
454                    if (jc->handle_floats_manually) {
455                        value.string_value = jc->parse_buffer;
456                        value.string_length = jc->parse_buffer_count;
457                    } else { 
458                        result = sscanf(jc->parse_buffer, "%Lf", &value.float_value);
459                    }
460                    break;
461                case JSON_T_INTEGER:
462                    arg = &value;
463                    result = sscanf(jc->parse_buffer, JSON_PARSER_INTEGER_SSCANF_TOKEN, &value.integer_value);
464                    break;
465                case JSON_T_STRING:
466                    arg = &value;
467                    value.string_value = jc->parse_buffer;
468                    value.string_length = jc->parse_buffer_count;
469                    break;
470            }
471           
472            if (!(*jc->callback)(jc->ctx, jc->type, arg)) {
473                return false;
474            }
475        }
476    }
477   
478    parse_buffer_clear(jc);
479   
480    return true;
481}
482
483static int decode_unicode_char(JSON_parser jc)
484{
485    const unsigned chars = jc->utf16_decode_buffer[0] ? 2 : 1;
486    int i;
487    UTF16 *uc = chars == 1 ? &jc->utf16_decode_buffer[0] : &jc->utf16_decode_buffer[1];
488    UTF16 x;
489    char* p;
490   
491    assert(jc->parse_buffer_count >= 6);
492   
493    p = &jc->parse_buffer[jc->parse_buffer_count - 4];
494   
495    for (i = 0; i < 4; ++i, ++p) {
496        x = *p;
497       
498        if (x >= 'a') {
499            x -= ('a' - 10);
500        } else if (x >= 'A') {
501            x -= ('A' - 10);
502        } else {
503            x &= ~((UTF16) 0x30);
504        }
505       
506        assert(x < 16);
507       
508        *uc |= x << ((3u - i) << 2);
509    }
510   
511    /* clear UTF-16 char form buffer */
512    jc->parse_buffer_count -= 6;
513    jc->parse_buffer[jc->parse_buffer_count] = 0;
514   
515    /* attempt decoding ... */
516    {
517        UTF8* dec_start = (UTF8*)&jc->parse_buffer[jc->parse_buffer_count];
518        UTF8* dec_start_dup = dec_start;
519        UTF8* dec_end = dec_start + 6;
520       
521        const UTF16* enc_start = &jc->utf16_decode_buffer[0];
522        const UTF16* enc_end = enc_start + chars;
523   
524        const ConversionResult result = ConvertUTF16toUTF8(
525            &enc_start, enc_end, &dec_start, dec_end, strictConversion);
526       
527        const size_t new_chars = dec_start - dec_start_dup;
528       
529        /* was it a surrogate UTF-16 char? */
530        if (chars == 1 && result == sourceExhausted) {
531            return true;
532        }
533       
534        if (result != conversionOK) {
535            return false;
536        }
537       
538        /* NOTE: clear decode buffer to resume string reading,
539           otherwise we continue to read UTF-16 */
540        jc->utf16_decode_buffer[0] = 0;
541       
542        assert(new_chars <= 6);
543       
544        jc->parse_buffer_count += new_chars;
545        jc->parse_buffer[jc->parse_buffer_count] = 0;
546    }
547   
548    return true;
549}
550
551
552int
553JSON_parser_char(JSON_parser jc, int next_char)
554{
555/*
556    After calling new_JSON_parser, call this function for each character (or
557    partial character) in your JSON text. It can accept UTF-8, UTF-16, or
558    UTF-32. It returns true if things are looking ok so far. If it rejects the
559    text, it returns false.
560*/
561    int next_class, next_state;
562   
563/*
564    Determine the character's class.
565*/
566    if (next_char < 0) {
567        return false;
568    }
569    if (next_char >= 128) {
570        next_class = C_ETC;
571    } else {
572        next_class = ascii_class[next_char];
573        if (next_class <= __) {
574            return false;
575        }
576    }
577   
578    if (jc->escaped) {
579        jc->escaped = 0;
580        /* remove the backslash */
581        parse_buffer_pop_back_char(jc);
582        switch(next_char) {
583        case 'b':
584            parse_buffer_push_back_char(jc, '\b');
585            break;
586        case 'f':
587            parse_buffer_push_back_char(jc, '\f');
588            break;
589        case 'n':
590            parse_buffer_push_back_char(jc, '\n');
591            break;
592        case 'r':
593            parse_buffer_push_back_char(jc, '\r');
594            break;
595        case 't':
596            parse_buffer_push_back_char(jc, '\t');
597            break;
598        case '"':
599            parse_buffer_push_back_char(jc, '"');
600            break;
601        case '\\':
602            parse_buffer_push_back_char(jc, '\\');
603            break;
604        case '/':
605            parse_buffer_push_back_char(jc, '/');
606            break;
607        case 'u':
608            parse_buffer_push_back_char(jc, '\\');
609            parse_buffer_push_back_char(jc, 'u');
610            break;
611        default:
612            return false;
613        }
614    } else if (!jc->comment) { 
615        if (jc->type != JSON_T_NONE || !(next_class == C_SPACE || next_class == C_WHITE) /* non-white-space */) {
616            parse_buffer_push_back_char(jc, (char)next_char);
617        }
618    }
619   
620   
621   
622/*
623    Get the next state from the state transition table.
624*/
625    next_state = state_transition_table[jc->state][next_class];
626    if (next_state >= 0) {
627/*
628    Change the state.
629*/
630        jc->state = next_state;
631    } else {
632/*
633    Or perform one of the actions.
634*/
635        switch (next_state) {
636/* Unicode character */       
637        case UC:
638            if(!decode_unicode_char(jc)) {
639                return false;
640            }
641            /* check if we need to read a second UTF-16 char */
642            if (jc->utf16_decode_buffer[0]) {
643                jc->state = D1;
644            } else {
645                jc->state = ST;
646            }
647            break;
648/* escaped char */
649        case EX:
650            jc->escaped = 1;
651            jc->state = ES;
652            break;
653/* integer detected by minus */
654        case MX:
655            jc->type = JSON_T_INTEGER;
656            jc->state = MI;
657            break; 
658/* integer detected by zero */           
659        case ZX:
660            jc->type = JSON_T_INTEGER;
661            jc->state = ZE;
662            break; 
663/* integer detected by 1-9 */           
664        case IX:
665            jc->type = JSON_T_INTEGER;
666            jc->state = IN;
667            break; 
668           
669/* floating point number detected by exponent*/
670        case DE:
671            assert(jc->type != JSON_T_FALSE);
672            assert(jc->type != JSON_T_TRUE);
673            assert(jc->type != JSON_T_NULL);
674            assert(jc->type != JSON_T_STRING);
675            jc->type = JSON_T_FLOAT;
676            jc->state = E1;
677            break;   
678       
679/* floating point number detected by fraction */
680        case DF:
681            assert(jc->type != JSON_T_FALSE);
682            assert(jc->type != JSON_T_TRUE);
683            assert(jc->type != JSON_T_NULL);
684            assert(jc->type != JSON_T_STRING);
685            jc->type = JSON_T_FLOAT;
686            jc->state = FX;
687            break;   
688/* string begin " */
689        case SB:
690            parse_buffer_clear(jc);
691            assert(jc->type == JSON_T_NONE);
692            jc->type = JSON_T_STRING;
693            jc->state = ST;
694            break;       
695       
696/* n */
697        case NU:
698            assert(jc->type == JSON_T_NONE);
699            jc->type = JSON_T_NULL;
700            jc->state = N1;
701            break;       
702/* f */
703        case FA:
704            assert(jc->type == JSON_T_NONE);
705            jc->type = JSON_T_FALSE;
706            jc->state = F1;
707            break;       
708/* t */
709        case TR:
710            assert(jc->type == JSON_T_NONE);
711            jc->type = JSON_T_TRUE;
712            jc->state = T1;
713            break;       
714       
715/* closing comment */
716        case CE:
717            jc->comment = 0;
718            assert(jc->parse_buffer_count == 0);
719            assert(jc->type == JSON_T_NONE);
720            jc->state = jc->before_comment_state;
721            break;       
722       
723/* opening comment  */
724        case CB:
725            if (!jc->allow_comments) {
726                return false;
727            }
728            parse_buffer_pop_back_char(jc);
729            if (!parse_parse_buffer(jc)) {
730                return false;
731            }
732            assert(jc->parse_buffer_count == 0);
733            assert(jc->type != JSON_T_STRING);
734            switch (jc->stack[jc->top]) {
735            case MODE_ARRAY:
736            case MODE_OBJECT:   
737                switch(jc->state) {
738                case VA:
739                case AR:
740                    jc->before_comment_state = jc->state;
741                    break;
742                default:
743                    jc->before_comment_state = OK;
744                    break;
745                }
746                break;
747            default:
748                jc->before_comment_state = jc->state;
749                break;
750            }
751            jc->type = JSON_T_NONE;
752            jc->state = C1;
753            jc->comment = 1;
754            break;
755/* empty } */
756        case -9:       
757            parse_buffer_clear(jc);
758            if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_END, NULL)) {
759                return false;
760            }
761            if (!pop(jc, MODE_KEY)) {
762                return false;
763            }
764            jc->state = OK;
765            break;
766
767/* } */ case -8:
768            parse_buffer_pop_back_char(jc);
769            if (!parse_parse_buffer(jc)) {
770                return false;
771            }
772            if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_END, NULL)) {
773                return false;
774            }
775            if (!pop(jc, MODE_OBJECT)) {
776                return false;
777            }
778            jc->type = JSON_T_NONE;
779            jc->state = OK;
780            break;
781
782/* ] */ case -7:
783            parse_buffer_pop_back_char(jc);
784            if (!parse_parse_buffer(jc)) {
785                return false;
786            }
787            if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_ARRAY_END, NULL)) {
788                return false;
789            }
790            if (!pop(jc, MODE_ARRAY)) {
791                return false;
792            }
793           
794            jc->type = JSON_T_NONE;
795            jc->state = OK;
796            break;
797
798/* { */ case -6:
799            parse_buffer_pop_back_char(jc);
800            if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_BEGIN, NULL)) {
801                return false;
802            }
803            if (!push(jc, MODE_KEY)) {
804                return false;
805            }
806            assert(jc->type == JSON_T_NONE);
807            jc->state = OB;
808            break;
809
810/* [ */ case -5:
811            parse_buffer_pop_back_char(jc);
812            if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_ARRAY_BEGIN, NULL)) {
813                return false;
814            }
815            if (!push(jc, MODE_ARRAY)) {
816                return false;
817            }
818            assert(jc->type == JSON_T_NONE);
819            jc->state = AR;
820            break;
821
822/* string end " */ case -4:
823            parse_buffer_pop_back_char(jc);
824            switch (jc->stack[jc->top]) {
825            case MODE_KEY:
826                assert(jc->type == JSON_T_STRING);
827                jc->type = JSON_T_NONE;
828                jc->state = CO;
829               
830                if (jc->callback) {
831                    JSON_value value;
832                    value.string_value = jc->parse_buffer;
833                    value.string_length = jc->parse_buffer_count;
834                    if (!(*jc->callback)(jc->ctx, JSON_T_KEY, &value)) {
835                        return false;
836                    }
837                }
838                parse_buffer_clear(jc);
839                break;
840            case MODE_ARRAY:
841            case MODE_OBJECT:
842                assert(jc->type == JSON_T_STRING);
843                if (!parse_parse_buffer(jc)) {
844                    return false;
845                }
846                jc->type = JSON_T_NONE;
847                jc->state = OK;
848                break;
849            default:
850                return false;
851            }
852            break;
853
854/* , */ case -3:
855            parse_buffer_pop_back_char(jc);
856            if (!parse_parse_buffer(jc)) {
857                return false;
858            }
859            switch (jc->stack[jc->top]) {
860            case MODE_OBJECT:
861/*
862    A comma causes a flip from object mode to key mode.
863*/
864                if (!pop(jc, MODE_OBJECT) || !push(jc, MODE_KEY)) {
865                    return false;
866                }
867                assert(jc->type != JSON_T_STRING);
868                jc->type = JSON_T_NONE;
869                jc->state = KE;
870                break;
871            case MODE_ARRAY:
872                assert(jc->type != JSON_T_STRING);
873                jc->type = JSON_T_NONE;
874                jc->state = VA;
875                break;
876            default:
877                return false;
878            }
879            break;
880
881/* : */ case -2:
882/*
883    A colon causes a flip from key mode to object mode.
884*/
885            parse_buffer_pop_back_char(jc);
886            if (!pop(jc, MODE_KEY) || !push(jc, MODE_OBJECT)) {
887                return false;
888            }
889            assert(jc->type == JSON_T_NONE);
890            jc->state = VA;
891            break;
892/*
893    Bad action.
894*/
895        default:
896            return false;
897        }
898    }
899    return true;
900}
901
902
903int
904JSON_parser_done(JSON_parser jc)
905{
906    const int result = jc->state == OK && pop(jc, MODE_DONE);
907
908    return result;
909}
910
911
912int JSON_parser_is_legal_white_space_string(const char* s)
913{
914    int c, char_class;
915   
916    if (s == NULL) {
917        return false;
918    }
919   
920    for (; *s; ++s) {   
921        c = *s;
922       
923        if (c < 0 || c >= 128) {
924            return false;
925        }
926       
927        char_class = ascii_class[c];
928       
929        if (char_class != C_SPACE && char_class != C_WHITE) {
930            return false;
931        }
932    }
933   
934    return true;
935}
936
937
938
939void init_JSON_config(JSON_config* config)
940{
941    if (config) {
942        memset(config, 0, sizeof(*config));
943       
944        config->depth = JSON_PARSER_STACK_SIZE - 1;
945    }
946}
Note: See TracBrowser for help on using the repository browser.