2
Copyright (c) 2009 Dave Gamble
3
Copyright (c) 2009 The OpenTyrian Development Team
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
of this software and associated documentation files (the "Software"), to deal
7
in the Software without restriction, including without limitation the rights
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the Software is
10
furnished to do so, subject to the following conditions:
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
#include "mingw_fixes.h"
39
static void *(*cJSON_malloc)( size_t ) = malloc;
40
static void *(*cJSON_realloc)( void *, size_t ) = realloc;
41
static void (*cJSON_free)( void *ptr ) = free;
43
// helper for compilers without strdup
44
static char *cJSON_strdup( const char *str )
46
size_t size = strlen(str) + 1;
47
char *copy = (char *)cJSON_malloc(size);
50
memcpy(copy, str, size);
55
// helper for compilers without strcasecmp
56
static int cJSON_strcasecmp( const char *s1, const char *s2 )
58
for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2)
61
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
64
// construct empty item
65
static cJSON *cJSON_NewItem( cJSON_Type type )
67
cJSON *node = (cJSON *)cJSON_malloc(sizeof(cJSON));
78
node->valuestring = NULL;
80
node->valuedouble = 0;
87
void cJSON_Delete( cJSON *item )
92
cJSON_Delete(item->child);
94
cJSON *next = item->next;
97
cJSON_free(item->string);
98
if (item->valuestring)
99
cJSON_free(item->valuestring);
106
// parser/emitter prototypes
108
static const char *parse_value( cJSON *item, const char *in );
109
static char *print_value(cJSON *item,int depth);
111
static const char *parse_number( cJSON *item, const char *in );
112
static char *print_number( cJSON *item );
114
static const char *parse_string(cJSON *item,const char *str);
115
static char *print_string(cJSON *item);
117
static const char *parse_array_or_object( cJSON *item, const char *in, cJSON_Type type );
118
static char *print_array(cJSON *item,int depth);
119
static char *print_object(cJSON *item,int depth);
121
static inline const char *parse_array( cJSON *item, const char *in )
123
return parse_array_or_object(item, in, cJSON_Array);
125
static inline const char *parse_object( cJSON *item, const char *in )
127
return parse_array_or_object(item, in, cJSON_Object);
130
// helper to skip whitespace
131
static inline const char *skip_space( const char *str )
134
while (isspace(*str))
139
// parse root of JSON into cJSON item
140
cJSON *cJSON_Parse( const char *in )
142
cJSON *item = cJSON_NewItem(cJSON_NULL);
146
if (parse_value(item, skip_space(in)) == NULL) // if malformed or out-of-memory
156
// emit cJSON item as JSON value
157
char *cJSON_Print( cJSON *item )
159
return print_value(item, 0);
162
// parse JSON value into cJSON item
163
static const char *parse_value( cJSON *item, const char *in )
168
if (!strncmp(in, "null", 4))
170
item->type = cJSON_NULL;
173
if (!strncmp(in, "false", 5))
175
item->type = cJSON_False;
178
if (!strncmp(in, "true", 4))
180
item->type = cJSON_True;
184
return parse_string(item, in);
185
if (*in == '-' || (*in >= '0' && *in <= '9'))
186
return parse_number(item, in);
188
return parse_array(item, in);
190
return parse_object(item, in);
192
return NULL; // malformed: expected value
195
// emit cJSON item as JSON value
196
static char *print_value( cJSON *item, int depth )
203
out = cJSON_strdup("null");
206
out = cJSON_strdup("false");
209
out = cJSON_strdup("true");
212
out = print_number(item);
215
out = print_string(item);
218
out = print_array(item, depth);
221
out = print_object(item, depth);
228
// parse JSON number value into cJSON item
229
static const char *parse_number( cJSON *item, const char *in )
232
int sign = 1, decimal_shift = 0;
233
int exponent_sign = 1, exponent = 0;
241
else if (*in >= '1' && *in <= '9')
243
n = (n * 10.0) + (*(in++) - '0');
244
while (*in >= '0' && *in <= '9');
251
while (*in >= '0' && *in <= '9')
252
n = (n * 10.0) + (*(in++) - '0'), decimal_shift--;
256
if (*in == 'e' || *in == 'E')
263
exponent_sign = -1, ++in;
265
while (*in >= '0' && *in <= '9')
266
exponent = (exponent * 10) + (*(in++) - '0');
269
// number = +/- number.fraction * (10 ^ +/- exponent)
270
n = sign * n * pow(10.0, decimal_shift + exponent_sign * exponent);
272
item->valuedouble = n;
274
item->type = cJSON_Number;
279
// emit string containing numeric value of cJSON item
280
static char *print_number( cJSON *item )
282
char *str = (char *)cJSON_malloc(DBL_DIG + 10);
283
snprintf(str, DBL_DIG + 10, "%.*g", DBL_DIG, item->valuedouble);
287
// Parse the input text into an unescaped cstring, and populate item.
288
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
289
static const char *parse_string(cJSON *item,const char *str)
291
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
292
if (*str!='\"') return 0; // not a string!
294
while (*ptr!='\"' && *ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // skip escaped quotes.
296
out=(char*)cJSON_malloc(len+1); // This is how long we need for the string, roughly.
300
while (*ptr!='\"' && *ptr>31)
302
if (*ptr!='\\') *ptr2++=*ptr++;
308
case 'b': *ptr2++='\b'; break;
309
case 'f': *ptr2++='\f'; break;
310
case 'n': *ptr2++='\n'; break;
311
case 'r': *ptr2++='\r'; break;
312
case 't': *ptr2++='\t'; break;
313
case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
314
sscanf(ptr+1,"%4x",&uc); // get the unicode char.
315
len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
318
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
319
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
320
case 1: *--ptr2 =(uc | firstByteMark[len]);
324
default: *ptr2++=*ptr; break;
330
if (*ptr=='\"') ptr++;
331
item->valuestring=out;
332
item->type=cJSON_String;
336
// Render the cstring provided to an escaped version that can be printed.
337
static char *print_string_ptr(const char *str)
339
const char *ptr;char *ptr2,*out;int len=0;
341
ptr=str;while (*ptr && ++len) {if (*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
343
out=(char*)cJSON_malloc(len+3);
348
if (*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
354
case '\\': *ptr2++='\\'; break;
355
case '\"': *ptr2++='\"'; break;
356
case '\b': *ptr2++='b'; break;
357
case '\f': *ptr2++='f'; break;
358
case '\n': *ptr2++='n'; break;
359
case '\r': *ptr2++='r'; break;
360
case '\t': *ptr2++='t'; break;
361
default: ptr2--; break; // eviscerate with prejudice.
365
*ptr2++='\"';*ptr2++=0;
368
// Invote print_string_ptr (which is useful) on an item.
369
static char *print_string(cJSON *item)
371
return (item->valuestring != NULL) ? print_string_ptr(item->valuestring) : cJSON_strdup("");
374
// parse JSON array/object into cJSON item chain
375
static const char *parse_array_or_object( cJSON *const item, const char *in, cJSON_Type type )
377
assert(type == cJSON_Array || type == cJSON_Object);
379
const char opening = (type == cJSON_Object) ? '{' : '[',
380
closing = (type == cJSON_Object) ? '}' : ']';
382
if (*in != opening) // not an array/object!
385
in = skip_space(++in);
389
if (*in == closing) // empty array/object
392
cJSON *prev_child = NULL;
395
cJSON *child = cJSON_NewItem(cJSON_NULL);
396
if (child == NULL) // memory fail
399
if (prev_child == NULL)
401
// attach first child to parent
406
// attach other children to older sibling
407
prev_child->next = child;
408
child->prev = prev_child;
411
if (type == cJSON_Object)
413
// object children have identifier string
415
in = skip_space(parse_string(child, skip_space(in)));
416
if (in == NULL) // malformed or memory fail
419
// parse_string parses into the item's value; we can use it to parse the identifier string, we just have to move the results
420
child->string = child->valuestring;
421
child->valuestring = NULL;
423
if (*in != ':') // malformed
429
in = skip_space(parse_value(child, skip_space(in)));
430
if (in == NULL) // malformed or memory fail
441
if (*in == closing) // end of array/object
444
return NULL; // malformed
447
// Render an array to text
448
static char *print_array(cJSON *item,int depth)
451
size_t len = 3; // minimum needed to print empty array
453
ptr = out = (char*)cJSON_malloc(len);
458
cJSON *child = item->child;
462
char *ret = print_value(child, depth + 1);
468
size_t ret_len = strlen(ret);
471
ptr = out = (char*)cJSON_realloc(out, len);
474
strcpy(ptr, ret); // strcat(out, ret);
481
strcpy(ptr, ", "); // strcat(out, ", ");
488
strcpy(ptr, "]"); // strcat(out, "]");
493
// Render an object to text.
494
static char *print_object(cJSON *item,int depth)
497
size_t len = 4 + depth; // minimum needed to print empty object
501
ptr = out = (char*)cJSON_malloc(len);
506
cJSON *child = item->child;
510
char *str = print_string_ptr(child->string);
516
size_t str_len = strlen(str);
518
char *ret = print_value(child, depth);
525
size_t ret_len = strlen(ret);
527
len += depth + str_len + ret_len + 4;
528
out = (char*)cJSON_realloc(out, len);
529
ptr = out + strlen(out);
531
for (int i = 0; i < depth; ++i)
534
strcpy(ptr, str); // strcat(out, str);
539
strcpy(ptr, ":\t"); // strcat(out, ":\t");
542
strcpy(ptr, ret); // strcat(out, ret);
549
strcpy(ptr, ",\n"); // strcat(out, ",\n");
554
strcpy(ptr, "\n"); // strcat(out, "\n");
563
for (int i = 0; i < depth; ++i)
566
strcpy(ptr, "}"); // strcat(out, "}");
571
// Get Array size/item / object item.
572
int cJSON_GetArraySize( cJSON *array )
575
cJSON *item = array->child;
577
item = item->next, ++size;
580
cJSON *cJSON_GetArrayItem( cJSON *array, int index )
582
cJSON *item = array->child;
583
while (item != NULL && index > 0)
584
item = item->next, --index;
587
cJSON *cJSON_GetObjectItem( cJSON *object, const char *string)
589
cJSON *item=object->child;
590
while (item != NULL && cJSON_strcasecmp(item->string, string) != 0)
595
cJSON *cJSON_CreateOrGetObjectItem( cJSON *object, const char *string )
597
cJSON *child = cJSON_GetObjectItem(object, string);
599
cJSON_AddItemToObject(object, string, child = cJSON_CreateNull());
604
// Utility for array list handling.
605
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
607
// Add item to array/object.
608
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
609
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
611
// remove all items from array/object
612
void cJSON_ClearArray( cJSON *array )
614
cJSON_Delete(array->child);
618
// create basic types
620
cJSON *cJSON_CreateNull( void )
622
return cJSON_NewItem(cJSON_NULL);
624
cJSON *cJSON_CreateBoolean( bool value )
626
return cJSON_NewItem(value ? cJSON_True : cJSON_False);
628
cJSON *cJSON_CreateNumber( double value )
630
cJSON *item = cJSON_NewItem(cJSON_Number);
631
item->valueint = item->valuedouble = value;
634
cJSON *cJSON_CreateString( const char *value )
636
cJSON *item = cJSON_NewItem(cJSON_String);
637
item->valuestring = cJSON_strdup(value);
640
cJSON *cJSON_CreateArray( void )
642
return cJSON_NewItem(cJSON_Array);
644
cJSON *cJSON_CreateObject( void )
646
return cJSON_NewItem(cJSON_Object);
649
void cJSON_ForceType( cJSON *item, cJSON_Type type )
651
if (item->type != type)
653
cJSON_Delete(item->child);
660
void cJSON_SetBoolean( cJSON *item, bool value )
662
cJSON_ForceType(item, value ? cJSON_True : cJSON_False);
664
void cJSON_SetNumber( cJSON *item, double value )
666
cJSON_ForceType(item, cJSON_Number);
667
item->valueint = item->valuedouble = value;
669
void cJSON_SetString( cJSON *item, const char *value )
671
cJSON_ForceType(item, cJSON_String);
672
cJSON_free(item->valuestring);
673
item->valuestring = cJSON_strdup(value);
677
cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
678
cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
679
cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
680
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}