32
32
#include <ctype.h>
33
33
#include "cJSON.h"
34
34
35
- static const char * ep ;
36
- //static const char *end_ptr;
37
-
38
- const char * cJSON_GetErrorPtr () {return ep ;}
39
-
40
35
static int cJSON_strcasecmp (const char * s1 ,const char * s2 )
41
36
{
42
37
if (!s1 ) return (s1 == s2 )?0 :1 ;if (!s2 ) return 1 ;
@@ -94,18 +89,41 @@ void cJSON_Delete(cJSON *c)
94
89
}
95
90
96
91
/* Parse the input text to generate a number, and populate the result into item. */
97
- static const char * parse_number (cJSON * item ,const char * num )
92
+ static char * * parse_number (cJSON * item , char * * num )
98
93
{
99
94
double n = 0 ,sign = 1 ,scale = 0 ;int subscale = 0 ,signsubscale = 1 ;
100
95
101
- /* Could use sscanf for this? */
102
- if (* num == '-' ) sign = -1 ,num ++ ; /* Has sign? */
103
- if (* num == '0' ) num ++ ; /* is zero */
104
- if (* num >='1' && * num <='9' ) do n = (n * 10.0 )+ (* num ++ - '0' ); while (* num >='0' && * num <='9' ); /* Number? */
105
- if (* num == '.' && num [1 ]>='0' && num [1 ]<='9' ) {num ++ ; do n = (n * 10.0 )+ (* num ++ - '0' ),scale -- ; while (* num >='0' && * num <='9' );} /* Fractional part? */
106
- if (* num == 'e' || * num == 'E' ) /* Exponent? */
107
- { num ++ ;if (* num == '+' ) num ++ ; else if (* num == '-' ) signsubscale = -1 ,num ++ ; /* With sign? */
108
- while (* num >='0' && * num <='9' ) subscale = (subscale * 10 )+ (* num ++ - '0' ); /* Number? */
96
+ if (* * num == '-' ) { /* Has sign? */
97
+ sign = -1 ;
98
+ (* num )++ ;
99
+ }
100
+ if (* * num == '0' ) /* is zero */
101
+ (* num )++ ;
102
+ if (* * num >='1' && * * num <='9' ) { /* Number? */
103
+ do {
104
+ n = (n * 10.0 )+ (* * num - '0' );
105
+ (* num )++ ;
106
+ } while (* * num >='0' && * * num <='9' );
107
+ }
108
+ if (* * num == '.' && (* num )[1 ]>='0' && (* num )[1 ]<='9' ) { /* Fractional part? */
109
+ (* num )++ ;
110
+ do {
111
+ n = (n * 10.0 )+ (* * num - '0' );
112
+ scale -- ;
113
+ (* num )++ ;
114
+ } while (* * num >='0' && * * num <='9' );
115
+ }
116
+ if (* * num == 'e' || * * num == 'E' ) /* Exponent? */
117
+ { (* num )++ ;
118
+ /* signed? */
119
+ if (* * num == '+' )
120
+ (* num )++ ;
121
+ else if (* * num == '-' )
122
+ signsubscale = -1 ,(* num )++ ;
123
+ while (* * num >='0' && * * num <='9' ) { /* Number? */
124
+ subscale = (subscale * 10 )+ (* * num - '0' );
125
+ (* num )++ ;
126
+ }
109
127
}
110
128
111
129
n = sign * n * pow (10.0 ,(scale + subscale * signsubscale )); /* number = +/- number.fraction * 10^+/- exponent */
@@ -141,17 +159,17 @@ static char *print_number(cJSON *item)
141
159
142
160
/* Parse the input text into an unescaped cstring, and populate item. */
143
161
static const unsigned char firstByteMark [7 ] = { 0x00 , 0x00 , 0xC0 , 0xE0 , 0xF0 , 0xF8 , 0xFC };
144
- static const char * parse_string (cJSON * item ,const char * str )
162
+ static char * * parse_string (cJSON * item , char * * str )
145
163
{
146
- const char * ptr = str + 1 ;char * ptr2 ;char * out ;int len = 0 ;unsigned uc ,uc2 ;
147
- if (* str != '\"' ) { ep = str ; return 0 ;} /* not a string! */
164
+ char * ptr = * str + 1 ;char * ptr2 ;char * out ;int len = 0 ;unsigned uc ,uc2 ;
165
+ if (* * str != '\"' ) return NULL ; /* not a string! */
148
166
149
167
while (* ptr != '\"' && * ptr && ++ len ) if (* ptr ++ == '\\' ) ptr ++ ; /* Skip escaped quotes. */
150
168
151
169
out = (char * )cJSON_malloc (len + 1 ); /* This is how long we need for the string, roughly. */
152
170
if (!out ) return 0 ;
153
171
154
- ptr = str + 1 ;ptr2 = out ;
172
+ ptr = * str + 1 ;ptr2 = out ;
155
173
while (* ptr != '\"' && * ptr )
156
174
{
157
175
if (* ptr != '\\' ) * ptr2 ++ = * ptr ++ ;
@@ -197,7 +215,8 @@ static const char *parse_string(cJSON *item,const char *str)
197
215
if (* ptr == '\"' ) ptr ++ ;
198
216
item -> valuestring = out ;
199
217
item -> type = cJSON_String ;
200
- return ptr ;
218
+ * str = ptr ;
219
+ return str ;
201
220
}
202
221
203
222
/* Render the cstring provided to an escaped version that can be printed. */
@@ -239,24 +258,31 @@ static char *print_string_ptr(const char *str)
239
258
static char * print_string (cJSON * item ) {return print_string_ptr (item -> valuestring );}
240
259
241
260
/* Predeclare these prototypes. */
242
- static const char * parse_value (cJSON * item ,const char * value );
261
+ static char * * parse_value (cJSON * item , char * * value );
243
262
static char * print_value (cJSON * item ,int depth ,int fmt );
244
- static const char * parse_array (cJSON * item ,const char * value );
263
+ static char * * parse_array (cJSON * item , char * * value );
245
264
static char * print_array (cJSON * item ,int depth ,int fmt );
246
- static const char * parse_object (cJSON * item ,const char * value );
265
+ static char * * parse_object (cJSON * item , char * * value );
247
266
static char * print_object (cJSON * item ,int depth ,int fmt );
248
267
249
268
/* Utility to jump whitespace and cr/lf */
250
- static const char * skip (const char * in ) {while (in && * in && (unsigned char )* in <=32 ) in ++ ; return in ;}
269
+ static inline char * * skip (char * * in )
270
+ {
271
+ if (in && * in )
272
+ while (isspace (* * in ))
273
+ (* in )++ ;
274
+ return in ;
275
+ }
251
276
252
277
/* Parse an object - create a new root, and populate. */
253
278
cJSON * cJSON_Parse (const char * value )
254
279
{
255
280
cJSON * c = cJSON_New_Item ();
256
- ep = 0 ;
257
281
if (!c ) return 0 ; /* memory fail */
258
282
259
- if (!parse_value (c ,skip (value ))) {cJSON_Delete (c );return 0 ;}
283
+ char * * end_ptr = (char * * )& value ;
284
+
285
+ if (!parse_value (c ,skip (end_ptr ))) {cJSON_Delete (c );return 0 ;}
260
286
return c ;
261
287
}
262
288
@@ -267,30 +293,53 @@ cJSON *cJSON_Parse_Stream(const char *value, char **end_ptr)
267
293
if (!end_ptr )
268
294
return NULL ;
269
295
cJSON * c = cJSON_New_Item ();
270
- ep = 0 ;
271
296
if (!c ) return 0 ; /* memory fail */
272
297
273
- if (!(* end_ptr = parse_value (c ,skip (value )))) {cJSON_Delete (c );return 0 ;}
298
+ * end_ptr = (char * )value ;
299
+
300
+ if (!parse_value (c ,skip (end_ptr ))) {cJSON_Delete (c );return 0 ;}
274
301
return c ;
275
302
}
276
303
277
304
/* Render a cJSON item/entity/structure to text. */
278
305
char * cJSON_Print (cJSON * item ) {return print_value (item ,0 ,1 );}
279
306
char * cJSON_PrintUnformatted (cJSON * item ) {return print_value (item ,0 ,0 );}
280
307
308
+ static int stream_cmp (char * * stream , const char * str )
309
+ {
310
+ while (* * stream == * str ) {
311
+ (* stream )++ ;
312
+ str ++ ;
313
+ }
314
+ if (* str == '\0' )
315
+ return 0 ;
316
+ return * * stream - * str ;
317
+ }
318
+
281
319
/* Parser core - when encountering text, process appropriately. */
282
- static const char * parse_value (cJSON * item ,const char * value )
320
+ static char * * parse_value (cJSON * item , char * * value )
283
321
{
284
- if (!value ) return 0 ; /* Fail on null. */
285
- if (!strncmp (value ,"null" ,4 )) { item -> type = cJSON_NULL ; return value + 4 ; }
286
- if (!strncmp (value ,"false" ,5 )) { item -> type = cJSON_False ; return value + 5 ; }
287
- if (!strncmp (value ,"true" ,4 )) { item -> type = cJSON_True ; item -> valueint = 1 ; return value + 4 ; }
288
- if (* value == '\"' ) { return parse_string (item ,value ); }
289
- if (* value == '-' || (* value >='0' && * value <='9' )) { return parse_number (item ,value ); }
290
- if (* value == '[' ) { return parse_array (item ,value ); }
291
- if (* value == '{' ) { return parse_object (item ,value ); }
292
-
293
- ep = value ;return 0 ; /* failure. */
322
+ if (!stream_cmp (value ,"null" )) {
323
+ item -> type = cJSON_NULL ;
324
+ return value ;
325
+ } else if (!stream_cmp (value ,"false" )) {
326
+ item -> type = cJSON_False ;
327
+ return value ;
328
+ } else if (!stream_cmp (value ,"true" )) {
329
+ item -> type = cJSON_True ;
330
+ item -> valueint = 1 ;
331
+ return value ;
332
+ }
333
+
334
+ switch (* * value ) {
335
+ case '"' : return parse_string (item ,value );
336
+ case '-' :
337
+ case '0' ...'9' : return parse_number (item ,value );
338
+ case '[' : return parse_array (item ,value );
339
+ case '{' : return parse_object (item ,value );
340
+ }
341
+
342
+ return NULL ; /* failure */
294
343
}
295
344
296
345
/* Render a value to text. */
@@ -312,33 +361,46 @@ static char *print_value(cJSON *item,int depth,int fmt)
312
361
}
313
362
314
363
/* Build an array from input text. */
315
- static const char * parse_array (cJSON * item ,const char * value )
364
+ static char * * parse_array (cJSON * item , char * * value )
316
365
{
317
366
cJSON * child ;
318
- if (* value != '[' ) {ep = value ;return 0 ;} /* not an array! */
367
+ if (* * value != '[' ) /* not an array! */
368
+ return NULL ;
319
369
320
370
item -> type = cJSON_Array ;
321
- value = skip (value + 1 );
322
- if (* value == ']' ) return value + 1 ; /* empty array. */
371
+ (* value )++ ;
372
+ skip (value );
373
+ if (* * value == ']' ) {
374
+ (* value )++ ;
375
+ return value ; /* empty array. */
376
+ }
323
377
324
378
item -> child = child = cJSON_New_Item ();
325
379
if (!item -> child ) return 0 ; /* memory fail */
326
- value = skip (parse_value (child ,skip ( value ))); /* skip any spacing, get the value. */
327
- if (! value ) return 0 ;
380
+ if (! skip (parse_value (child ,value ))) /* skip any spacing, get the value. */
381
+ return NULL ;
328
382
329
- while (* value == ',' )
383
+ while (* * value == ',' )
330
384
{
331
- const char * nextch = skip (value + 1 );
332
- if (nextch != 0 && * nextch == ']' ) {value = nextch ;break ;}
385
+ (* value )++ ;
386
+ skip (value );
387
+ if (* * value == ']' ) {
388
+ (* value )++ ;
389
+ break ;
390
+ }
391
+
333
392
cJSON * new_item ;
334
393
if (!(new_item = cJSON_New_Item ())) return 0 ; /* memory fail */
335
394
child -> next = new_item ;new_item -> prev = child ;child = new_item ;
336
- value = skip (parse_value (child ,nextch ));
337
- if (! value ) return 0 ; /* memory fail */
395
+ if (! skip (parse_value (child ,value )))
396
+ return 0 ; /* memory fail */
338
397
}
339
398
340
- if (* value == ']' ) return value + 1 ; /* end of array */
341
- ep = value ;return 0 ; /* malformed. */
399
+ if (* * value != ']' )
400
+ return NULL ;
401
+ (* value )++ ;
402
+
403
+ return value ;
342
404
}
343
405
344
406
/* Render an array to text */
@@ -393,41 +455,56 @@ static char *print_array(cJSON *item,int depth,int fmt)
393
455
}
394
456
395
457
/* Build an object from the text. */
396
- static const char * parse_object (cJSON * item ,const char * value )
458
+ static char * * parse_object (cJSON * item , char * * value )
397
459
{
398
460
cJSON * child ;
399
- if (* value != '{' ) { ep = value ; return 0 ;} /* not an object! */
461
+ if (* * value != '{' ) return NULL ; /* not an object! */
400
462
401
463
item -> type = cJSON_Object ;
402
- value = skip (value + 1 );
403
- if (* value == '}' ) return value + 1 ; /* empty array. */
464
+ (* value )++ ;
465
+ skip (value );
466
+ if (* * value == '}' ) {
467
+ (* value )++ ;
468
+ return value ; /* empty object. */
469
+ }
404
470
405
471
item -> child = child = cJSON_New_Item ();
406
472
if (!item -> child ) return 0 ;
407
- value = skip (parse_string (child ,skip ( value )));
408
- if (! value ) return 0 ;
473
+ if (! skip (parse_string (child ,value )))
474
+ return 0 ;
409
475
child -> string = child -> valuestring ;child -> valuestring = 0 ;
410
- if (* value != ':' ) {ep = value ;return 0 ;} /* fail! */
411
- value = skip (parse_value (child ,skip (value + 1 ))); /* skip any spacing, get the value. */
412
- if (!value ) return 0 ;
476
+ if (* * value != ':' ) return NULL ; /* fail! */
477
+ (* value )++ ;
478
+ if (!skip (parse_value (child ,skip (value )))) /* skip any spacing, get the value. */
479
+ return 0 ;
413
480
414
- while (* value == ',' )
481
+ while (* * value == ',' )
415
482
{
416
- const char * nextch = skip (value + 1 );
417
- if (nextch != 0 && * nextch == '}' ) {value = nextch ;break ;}
483
+ (* value )++ ;
484
+ skip (value );
485
+
486
+ if (* * value == '}' ) {
487
+ (* value )++ ;
488
+ break ;
489
+ }
490
+
418
491
cJSON * new_item ;
419
492
if (!(new_item = cJSON_New_Item ())) return 0 ; /* memory fail */
420
493
child -> next = new_item ;new_item -> prev = child ;child = new_item ;
421
- value = skip (parse_string (child ,nextch ));
422
- if (! value ) return 0 ;
494
+ if (! skip (parse_string (child ,value )))
495
+ return 0 ;
423
496
child -> string = child -> valuestring ;child -> valuestring = 0 ;
424
- if (* value != ':' ) {ep = value ;return 0 ;} /* fail! */
425
- value = skip (parse_value (child ,skip (value + 1 ))); /* skip any spacing, get the value. */
426
- if (!value ) return 0 ;
497
+ if (* * value != ':' ) return NULL ; /* fail! */
498
+ (* value )++ ;
499
+ if (!skip (parse_value (child ,skip (value )))) /* skip any spacing, get the value. */
500
+ return 0 ;
427
501
}
428
502
429
- if (* value == '}' ) return value + 1 ; /* end of array */
430
- ep = value ;return 0 ; /* malformed. */
503
+ if (* * value != '}' )
504
+ return NULL ;
505
+ (* value )++ ;
506
+
507
+ return value ;
431
508
}
432
509
433
510
/* Render an object to text. */
0 commit comments