16e7c7370SDerry/*
26e7c7370SDerry  Copyright (c) 2009 Dave Gamble
36e7c7370SDerry
46e7c7370SDerry  Permission is hereby granted, free of charge, to any person obtaining a copy
56e7c7370SDerry  of this software and associated documentation files (the "Software"), to deal
66e7c7370SDerry  in the Software without restriction, including without limitation the rights
76e7c7370SDerry  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
86e7c7370SDerry  copies of the Software, and to permit persons to whom the Software is
96e7c7370SDerry  furnished to do so, subject to the following conditions:
106e7c7370SDerry
116e7c7370SDerry  The above copyright notice and this permission notice shall be included in
126e7c7370SDerry  all copies or substantial portions of the Software.
136e7c7370SDerry
146e7c7370SDerry  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156e7c7370SDerry  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166e7c7370SDerry  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
176e7c7370SDerry  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
186e7c7370SDerry  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
196e7c7370SDerry  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
206e7c7370SDerry  THE SOFTWARE.
216e7c7370SDerry*/
226e7c7370SDerry
236e7c7370SDerry// cJSON
246e7c7370SDerry// JSON parser in C.
256e7c7370SDerry
266e7c7370SDerry#if 0
276e7c7370SDerry#include <string.h>
286e7c7370SDerry#include <stdio.h>
296e7c7370SDerry#include <math.h>
306e7c7370SDerry#include <stdlib.h>
316e7c7370SDerry#include <float.h>
326e7c7370SDerry#endif
336e7c7370SDerry
346e7c7370SDerry#include "cJSON.h"
356e7c7370SDerry
366e7c7370SDerry#include <linux/module.h>
376e7c7370SDerry#include <linux/slab.h>
386e7c7370SDerry
396e7c7370SDerry#if 0
406e7c7370SDerry#if defined(WINDOWS) || defined(__WIN32__) || defined(WIN32) || defined(_WIN32)
416e7c7370SDerry#define strcasecmp stricmp
426e7c7370SDerry#define strdup _strdup
436e7c7370SDerry#endif
446e7c7370SDerry#endif
456e7c7370SDerry
466e7c7370SDerry
476e7c7370SDerry#if 0
486e7c7370SDerrystatic void *(*cJSON_malloc)(size_t sz) = malloc;
496e7c7370SDerrystatic void *(*cJSON_realloc)(void *ptr, size_t sz) = realloc;
506e7c7370SDerrystatic void (*cJSON_free)(void *ptr) = free;
516e7c7370SDerry#endif
526e7c7370SDerry
536e7c7370SDerrystatic void *cJSON_malloc(size_t sz) {
546e7c7370SDerry	return kmalloc(sz, GFP_KERNEL);
556e7c7370SDerry}
566e7c7370SDerry
576e7c7370SDerrystatic void *cJSON_realloc(void *ptr, size_t sz)
586e7c7370SDerry{
596e7c7370SDerry	return krealloc(ptr, sz, GFP_KERNEL);
606e7c7370SDerry}
616e7c7370SDerry
626e7c7370SDerrystatic void cJSON_free(void *ptr)
636e7c7370SDerry{
646e7c7370SDerry	 kfree(ptr);
656e7c7370SDerry}
666e7c7370SDerry
676e7c7370SDerrystatic char* cJSON_strdup(const char* str)
686e7c7370SDerry{
696e7c7370SDerry      size_t len;
706e7c7370SDerry      char* copy;
716e7c7370SDerry
726e7c7370SDerry      len = strlen(str) + 1;
736e7c7370SDerry      if (!(copy = (char*)cJSON_malloc(len))) return 0;
746e7c7370SDerry      memcpy(copy,str,len);
756e7c7370SDerry      return copy;
766e7c7370SDerry}
776e7c7370SDerry
786e7c7370SDerry#if 0
796e7c7370SDerryvoid cJSON_InitHooks(cJSON_Hooks* hooks)
806e7c7370SDerry{
816e7c7370SDerry    if (!hooks) { /* Reset hooks */
826e7c7370SDerry        cJSON_malloc = malloc;
836e7c7370SDerry        cJSON_realloc = realloc;
846e7c7370SDerry        cJSON_free = free;
856e7c7370SDerry        return;
866e7c7370SDerry    }
876e7c7370SDerry
886e7c7370SDerry	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
896e7c7370SDerry	cJSON_realloc= (hooks->realloc_fn)?hooks->realloc_fn:realloc;
906e7c7370SDerry	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
916e7c7370SDerry}
926e7c7370SDerry#endif
936e7c7370SDerry
946e7c7370SDerry// Internal constructor.
956e7c7370SDerrystatic cJSON *cJSON_New_Item(void)
966e7c7370SDerry{
976e7c7370SDerry	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
986e7c7370SDerry	if (node) memset(node,0,sizeof(cJSON));
996e7c7370SDerry	return node;
1006e7c7370SDerry}
1016e7c7370SDerry
1026e7c7370SDerry// Delete a cJSON structure.
1036e7c7370SDerryvoid cJSON_Delete(cJSON *c)
1046e7c7370SDerry{
1056e7c7370SDerry	cJSON *next;
1066e7c7370SDerry	while (c)
1076e7c7370SDerry	{
1086e7c7370SDerry		next=c->next;
1096e7c7370SDerry		if (c->child) cJSON_Delete(c->child);
1106e7c7370SDerry		if (c->valuestring) cJSON_free(c->valuestring);
1116e7c7370SDerry		if (c->string) cJSON_free(c->string);
1126e7c7370SDerry		cJSON_free(c);
1136e7c7370SDerry		c=next;
1146e7c7370SDerry	}
1156e7c7370SDerry}
1166e7c7370SDerry
1176e7c7370SDerry
1186e7c7370SDerry/* Parse the input text to generate a number, and populate the result into item. */
1196e7c7370SDerrystatic const char *parse_number(cJSON *item,const char *num)
1206e7c7370SDerry{
12118728fe0Sderry	int n=0,sign=1;
1226e7c7370SDerry
1236e7c7370SDerry	if (*num=='-') sign=-1,num++;	/* Has sign? */
1246e7c7370SDerry	if (*num=='0') num++;			/* is zero */
1256e7c7370SDerry	if (*num>='1' && *num<='9')	do	n=(n*10)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
1266e7c7370SDerry	item->valueint=(int)n;
1276e7c7370SDerry	item->type=cJSON_Number;
1286e7c7370SDerry	return num;
1296e7c7370SDerry}
1306e7c7370SDerry
1316e7c7370SDerry/* Render the number nicely from the given item into a string. */
1326e7c7370SDerrystatic char *print_number(cJSON *item)
1336e7c7370SDerry{
1346e7c7370SDerry	char *str;
1356e7c7370SDerry	str=(char*)cJSON_malloc(21);
1366e7c7370SDerry	if (str)
1376e7c7370SDerry		sprintf(str,"%d",item->valueint);
1386e7c7370SDerry	return str;
1396e7c7370SDerry}
1406e7c7370SDerry
1416e7c7370SDerry
1426e7c7370SDerry// Parse the input text into an unescaped cstring, and populate item.
1436e7c7370SDerrystatic const char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
1446e7c7370SDerrystatic const char *parse_string(cJSON *item,const char *str)
1456e7c7370SDerry{
1466e7c7370SDerry	const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
1476e7c7370SDerry	if (*str!='\"') return 0;	// not a string!
1486e7c7370SDerry
1496e7c7370SDerry	while (*ptr!='\"' && *ptr>31 && ++len) if (*ptr++ == '\\') ptr++;	// Skip escaped quotes.
1506e7c7370SDerry
1516e7c7370SDerry	out=(char*)cJSON_malloc(len+1);	// This is how long we need for the string, roughly.
1526e7c7370SDerry	if (!out) return 0;
1536e7c7370SDerry
1546e7c7370SDerry	ptr=str+1;ptr2=out;
1556e7c7370SDerry	while (*ptr!='\"' && *ptr>31)
1566e7c7370SDerry	{
1576e7c7370SDerry		if (*ptr!='\\') *ptr2++=*ptr++;
1586e7c7370SDerry		else
1596e7c7370SDerry		{
1606e7c7370SDerry			ptr++;
1616e7c7370SDerry			switch (*ptr)
1626e7c7370SDerry			{
1636e7c7370SDerry				case 'b': *ptr2++='\b';	break;
1646e7c7370SDerry				case 'f': *ptr2++='\f';	break;
1656e7c7370SDerry				case 'n': *ptr2++='\n';	break;
1666e7c7370SDerry				case 'r': *ptr2++='\r';	break;
1676e7c7370SDerry				case 't': *ptr2++='\t';	break;
1686e7c7370SDerry				case 'u':	 // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
1696e7c7370SDerry					sscanf(ptr+1,"%4x",&uc);	// get the unicode char.
1706e7c7370SDerry					len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
1716e7c7370SDerry
1726e7c7370SDerry					switch (len) {
1736e7c7370SDerry						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
1746e7c7370SDerry						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
1756e7c7370SDerry						case 1: *--ptr2 =(uc | firstByteMark[len]);
1766e7c7370SDerry					}
1776e7c7370SDerry					ptr2+=len;ptr+=4;
1786e7c7370SDerry					break;
1796e7c7370SDerry				default:  *ptr2++=*ptr; break;
1806e7c7370SDerry			}
1816e7c7370SDerry			ptr++;
1826e7c7370SDerry		}
1836e7c7370SDerry	}
1846e7c7370SDerry	*ptr2=0;
1856e7c7370SDerry	if (*ptr=='\"') ptr++;
1866e7c7370SDerry	item->valuestring=out;
1876e7c7370SDerry	item->type=cJSON_String;
1886e7c7370SDerry	return ptr;
1896e7c7370SDerry}
1906e7c7370SDerry
1916e7c7370SDerry// Render the cstring provided to an escaped version that can be printed.
1926e7c7370SDerrystatic char *print_string_ptr(const char *str)
1936e7c7370SDerry{
1946e7c7370SDerry	const char *ptr;char *ptr2,*out;int len=0;
1956e7c7370SDerry
1966e7c7370SDerry	ptr=str;while (*ptr && ++len) {if (*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
1976e7c7370SDerry
1986e7c7370SDerry	out=(char*)cJSON_malloc(len+3);
1996e7c7370SDerry	ptr2=out;ptr=str;
2006e7c7370SDerry	*ptr2++='\"';
2016e7c7370SDerry	while (*ptr)
2026e7c7370SDerry	{
2036e7c7370SDerry		if (*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
2046e7c7370SDerry		else
2056e7c7370SDerry		{
2066e7c7370SDerry			*ptr2++='\\';
2076e7c7370SDerry			switch (*ptr++)
2086e7c7370SDerry			{
2096e7c7370SDerry				case '\\':	*ptr2++='\\';	break;
2106e7c7370SDerry				case '\"':	*ptr2++='\"';	break;
2116e7c7370SDerry				case '\b':	*ptr2++='b';	break;
2126e7c7370SDerry				case '\f':	*ptr2++='f';	break;
2136e7c7370SDerry				case '\n':	*ptr2++='n';	break;
2146e7c7370SDerry				case '\r':	*ptr2++='r';	break;
2156e7c7370SDerry				case '\t':	*ptr2++='t';	break;
2166e7c7370SDerry				default: ptr2--;	break;	// eviscerate with prejudice.
2176e7c7370SDerry			}
2186e7c7370SDerry		}
2196e7c7370SDerry	}
2206e7c7370SDerry	*ptr2++='\"';*ptr2++=0;
2216e7c7370SDerry	return out;
2226e7c7370SDerry}
2236e7c7370SDerry// Invote print_string_ptr (which is useful) on an item.
2246e7c7370SDerrystatic char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}
2256e7c7370SDerry
2266e7c7370SDerry// Predeclare these prototypes.
2276e7c7370SDerrystatic const char *parse_value(cJSON *item,const char *value);
2286e7c7370SDerrystatic char *print_value(cJSON *item,int depth);
2296e7c7370SDerrystatic const char *parse_array(cJSON *item,const char *value);
2306e7c7370SDerrystatic char *print_array(cJSON *item,int depth);
2316e7c7370SDerrystatic const char *parse_object(cJSON *item,const char *value);
2326e7c7370SDerrystatic char *print_object(cJSON *item,int depth);
2336e7c7370SDerry
2346e7c7370SDerry// Utility to jump whitespace and cr/lf
2356e7c7370SDerrystatic const char *skip(const char *in) {while (in && *in<=32) in++; return in;}
2366e7c7370SDerry
2376e7c7370SDerry// Parse an object - create a new root, and populate.
2386e7c7370SDerrycJSON *cJSON_Parse(const char *value)
2396e7c7370SDerry{
2406e7c7370SDerry	cJSON *c=cJSON_New_Item();
2416e7c7370SDerry	if (!c) return 0;       /* memory fail */
2426e7c7370SDerry
2436e7c7370SDerry	if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
2446e7c7370SDerry	return c;
2456e7c7370SDerry}
2466e7c7370SDerry
2476e7c7370SDerry// Render a cJSON item/entity/structure to text.
2486e7c7370SDerrychar *cJSON_Print(cJSON *item)			{return print_value(item,0);}
2496e7c7370SDerry
2506e7c7370SDerry// Parser core - when encountering text, process appropriately.
2516e7c7370SDerrystatic const char *parse_value(cJSON *item,const char *value)
2526e7c7370SDerry{
2536e7c7370SDerry	if (!value)						return 0;	// Fail on null.
2546e7c7370SDerry	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
2556e7c7370SDerry	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
2566e7c7370SDerry	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
2576e7c7370SDerry	if (*value=='\"')				{ return parse_string(item,value); }
2586e7c7370SDerry	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
2596e7c7370SDerry	if (*value=='[')				{ return parse_array(item,value); }
2606e7c7370SDerry	if (*value=='{')				{ return parse_object(item,value); }
2616e7c7370SDerry
2626e7c7370SDerry	return 0;	// failure.
2636e7c7370SDerry}
2646e7c7370SDerry
2656e7c7370SDerry// Render a value to text.
2666e7c7370SDerrystatic char *print_value(cJSON *item,int depth)
2676e7c7370SDerry{
2686e7c7370SDerry	char *out=0;
2696e7c7370SDerry	switch (item->type)
2706e7c7370SDerry	{
2716e7c7370SDerry		case cJSON_NULL:	out=cJSON_strdup("null");	break;
2726e7c7370SDerry		case cJSON_False:	out=cJSON_strdup("false");break;
2736e7c7370SDerry		case cJSON_True:	out=cJSON_strdup("true"); break;
2746e7c7370SDerry		case cJSON_Number:	out=print_number(item);break;
2756e7c7370SDerry		case cJSON_String:	out=print_string(item);break;
2766e7c7370SDerry		case cJSON_Array:	out=print_array(item,depth);break;
2776e7c7370SDerry		case cJSON_Object:	out=print_object(item,depth);break;
2786e7c7370SDerry	}
2796e7c7370SDerry	return out;
2806e7c7370SDerry}
2816e7c7370SDerry
2826e7c7370SDerry// Build an array from input text.
2836e7c7370SDerrystatic const char *parse_array(cJSON *item,const char *value)
2846e7c7370SDerry{
2856e7c7370SDerry	cJSON *child;
2866e7c7370SDerry	if (*value!='[')	return 0;	// not an array!
2876e7c7370SDerry
2886e7c7370SDerry	item->type=cJSON_Array;
2896e7c7370SDerry	value=skip(value+1);
2906e7c7370SDerry	if (*value==']') return value+1;	// empty array.
2916e7c7370SDerry
2926e7c7370SDerry	item->child=child=cJSON_New_Item();
2936e7c7370SDerry	if (!item->child) return 0;		 // memory fail
2946e7c7370SDerry	value=skip(parse_value(child,skip(value)));	// skip any spacing, get the value.
2956e7c7370SDerry	if (!value) return 0;
2966e7c7370SDerry
2976e7c7370SDerry	while (*value==',')
2986e7c7370SDerry	{
2996e7c7370SDerry		cJSON *new_item;
3006e7c7370SDerry		if (!(new_item=cJSON_New_Item())) return 0; 	// memory fail
3016e7c7370SDerry		child->next=new_item;new_item->prev=child;child=new_item;
3026e7c7370SDerry		value=skip(parse_value(child,skip(value+1)));
3036e7c7370SDerry		if (!value) return 0;	// memory fail
3046e7c7370SDerry	}
3056e7c7370SDerry
3066e7c7370SDerry	if (*value==']') return value+1;	// end of array
3076e7c7370SDerry	return 0;	// malformed.
3086e7c7370SDerry}
3096e7c7370SDerry
3106e7c7370SDerry// Render an array to text
3116e7c7370SDerrystatic char *print_array(cJSON *item,int depth)
3126e7c7370SDerry{
3136e7c7370SDerry	char *out,*ptr,*ret;int len=5;
3146e7c7370SDerry	cJSON *child=item->child;
3156e7c7370SDerry
3166e7c7370SDerry	out=(char*)cJSON_malloc(len);*out='[';
3176e7c7370SDerry	ptr=out+1;*ptr=0;
3186e7c7370SDerry	while (child)
3196e7c7370SDerry	{
3206e7c7370SDerry		ret=print_value(child,depth+1);
3216e7c7370SDerry		if (!ret) {cJSON_free(out);return 0;}	// Check for failure!
3226e7c7370SDerry		len+=strlen(ret)+3;
3236e7c7370SDerry		out=(char*)cJSON_realloc(out,len);
3246e7c7370SDerry		ptr=out+strlen(out);
3256e7c7370SDerry		ptr+=sprintf(ptr,ret);
3266e7c7370SDerry		if (child->next) {*ptr++=',';*ptr++=' ';*ptr=0;}
3276e7c7370SDerry		child=child->next;
3286e7c7370SDerry		cJSON_free(ret);
3296e7c7370SDerry	}
3306e7c7370SDerry	*ptr++=']';*ptr++=0;
3316e7c7370SDerry	return out;
3326e7c7370SDerry}
3336e7c7370SDerry
3346e7c7370SDerry// Build an object from the text.
3356e7c7370SDerrystatic const char *parse_object(cJSON *item,const char *value)
3366e7c7370SDerry{
3376e7c7370SDerry	cJSON *child;
3386e7c7370SDerry	if (*value!='{')	return 0;	// not an object!
3396e7c7370SDerry
3406e7c7370SDerry	item->type=cJSON_Object;
3416e7c7370SDerry	value=skip(value+1);
3426e7c7370SDerry	if (*value=='}') return value+1;	// empty array.
3436e7c7370SDerry
3446e7c7370SDerry	item->child=child=cJSON_New_Item();
3456e7c7370SDerry	value=skip(parse_string(child,skip(value)));
3466e7c7370SDerry	if (!value) return 0;
3476e7c7370SDerry	child->string=child->valuestring;child->valuestring=0;
3486e7c7370SDerry	if (*value!=':') return 0;	// fail!
3496e7c7370SDerry	value=skip(parse_value(child,skip(value+1)));	// skip any spacing, get the value.
3506e7c7370SDerry	if (!value) return 0;
3516e7c7370SDerry
3526e7c7370SDerry	while (*value==',')
3536e7c7370SDerry	{
3546e7c7370SDerry		cJSON *new_item;
3556e7c7370SDerry		if (!(new_item=cJSON_New_Item()))	return 0; // memory fail
3566e7c7370SDerry		child->next=new_item;new_item->prev=child;child=new_item;
3576e7c7370SDerry		value=skip(parse_string(child,skip(value+1)));
3586e7c7370SDerry		if (!value) return 0;
3596e7c7370SDerry		child->string=child->valuestring;child->valuestring=0;
3606e7c7370SDerry		if (*value!=':') return 0;	// fail!
3616e7c7370SDerry		value=skip(parse_value(child,skip(value+1)));	// skip any spacing, get the value.
3626e7c7370SDerry		if (!value) return 0;
3636e7c7370SDerry	}
3646e7c7370SDerry
3656e7c7370SDerry	if (*value=='}') return value+1;	// end of array
3666e7c7370SDerry	return 0;	// malformed.
3676e7c7370SDerry}
3686e7c7370SDerry
3696e7c7370SDerry// Render an object to text.
3706e7c7370SDerrystatic char *print_object(cJSON *item,int depth)
3716e7c7370SDerry{
3726e7c7370SDerry	char *out,*ptr,*ret,*str;int len=7,i;
3736e7c7370SDerry	cJSON *child=item->child;
3746e7c7370SDerry
3756e7c7370SDerry	depth++;len+=depth;out=(char*)cJSON_malloc(len);*out='{';
3766e7c7370SDerry	ptr=out+1;*ptr++='\n';*ptr=0;
3776e7c7370SDerry	while (child)
3786e7c7370SDerry	{
3796e7c7370SDerry		str=print_string_ptr(child->string);
3806e7c7370SDerry		if (!str) {cJSON_free(out);return 0;}
3816e7c7370SDerry		ret=print_value(child,depth);
3826e7c7370SDerry		if (!ret) {cJSON_free(str);cJSON_free(out);return 0;}	// Check for failure!
3836e7c7370SDerry		len+=strlen(ret)+strlen(str)+4+depth;
3846e7c7370SDerry		out=(char*)cJSON_realloc(out,len);
3856e7c7370SDerry		ptr=out+strlen(out);
3866e7c7370SDerry		for (i=0;i<depth;i++) *ptr++='\t';
3876e7c7370SDerry		ptr+=sprintf(ptr,str);
3886e7c7370SDerry		*ptr++=':';*ptr++='\t';
3896e7c7370SDerry		ptr+=sprintf(ptr,ret);
3906e7c7370SDerry		if (child->next) *ptr++=',';
3916e7c7370SDerry		*ptr++='\n';*ptr=0;
3926e7c7370SDerry		child=child->next;
3936e7c7370SDerry		cJSON_free(str);cJSON_free(ret);
3946e7c7370SDerry	}
3956e7c7370SDerry	for (i=0;i<depth-1;i++) *ptr++='\t';
3966e7c7370SDerry	*ptr++='}';*ptr++=0;
3976e7c7370SDerry	return out;
3986e7c7370SDerry}
3990055281cSdestan#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
4000055281cSdestan
4010055281cSdestanstatic void skip_oneline_comment(char **input)
4020055281cSdestan{
4030055281cSdestan    *input += static_strlen("//");
4040055281cSdestan
4050055281cSdestan    for (; (*input)[0] != '\0'; ++(*input))
4060055281cSdestan    {
4070055281cSdestan        if ((*input)[0] == '\n') {
4080055281cSdestan            *input += static_strlen("\n");
4090055281cSdestan            return;
4100055281cSdestan        }
4110055281cSdestan    }
4120055281cSdestan}
4130055281cSdestanstatic void skip_multiline_comment(char **input)
4140055281cSdestan{
4150055281cSdestan    *input += static_strlen("/*");
4160055281cSdestan
4170055281cSdestan    for (; (*input)[0] != '\0'; ++(*input))
4180055281cSdestan    {
4190055281cSdestan        if (((*input)[0] == '*') && ((*input)[1] == '/'))
4200055281cSdestan        {
4210055281cSdestan            *input += static_strlen("*/");
4220055281cSdestan            return;
4230055281cSdestan        }
4240055281cSdestan    }
4250055281cSdestan}
4260055281cSdestanstatic void minify_string(char **input, char **output) {
4270055281cSdestan    (*output)[0] = (*input)[0];
4280055281cSdestan    *input += static_strlen("\"");
4290055281cSdestan    *output += static_strlen("\"");
4300055281cSdestan
4310055281cSdestan
4320055281cSdestan    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
4330055281cSdestan        (*output)[0] = (*input)[0];
4340055281cSdestan
4350055281cSdestan        if ((*input)[0] == '\"') {
4360055281cSdestan            (*output)[0] = '\"';
4370055281cSdestan            *input += static_strlen("\"");
4380055281cSdestan            *output += static_strlen("\"");
4390055281cSdestan            return;
4400055281cSdestan        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
4410055281cSdestan            (*output)[1] = (*input)[1];
4420055281cSdestan            *input += static_strlen("\"");
4430055281cSdestan            *output += static_strlen("\"");
4440055281cSdestan        }
4450055281cSdestan    }
4460055281cSdestan}
4470055281cSdestan
4480055281cSdestanvoid cJSON_Minify(char *json)
4490055281cSdestan{
4500055281cSdestan    char *into = json;
4510055281cSdestan
4520055281cSdestan    if (json == NULL)
4530055281cSdestan    {
4540055281cSdestan        return;
4550055281cSdestan    }
4560055281cSdestan
4570055281cSdestan    while (json[0] != '\0')
4580055281cSdestan    {
4590055281cSdestan        switch (json[0])
4600055281cSdestan        {
4610055281cSdestan            case ' ':
4620055281cSdestan            case '\t':
4630055281cSdestan            case '\r':
4640055281cSdestan            case '\n':
4650055281cSdestan                json++;
4660055281cSdestan                break;
4670055281cSdestan
4680055281cSdestan            case '/':
4690055281cSdestan                if (json[1] == '/')
4700055281cSdestan                {
4710055281cSdestan                    skip_oneline_comment(&json);
4720055281cSdestan                }
4730055281cSdestan                else if (json[1] == '*')
4740055281cSdestan                {
4750055281cSdestan                    skip_multiline_comment(&json);
4760055281cSdestan                } else {
4770055281cSdestan                    json++;
4780055281cSdestan                }
4790055281cSdestan                break;
4800055281cSdestan
4810055281cSdestan            case '\"':
4820055281cSdestan                minify_string(&json, (char**)&into);
4830055281cSdestan                break;
4840055281cSdestan
4850055281cSdestan            default:
4860055281cSdestan                into[0] = json[0];
4870055281cSdestan                json++;
4880055281cSdestan                into++;
4890055281cSdestan        }
4900055281cSdestan    }
4910055281cSdestan
4920055281cSdestan    /* and null-terminate. */
4930055281cSdestan    *into = '\0';
4940055281cSdestan}
4956e7c7370SDerry
4966e7c7370SDerry// Get Array size/item / object item.
4976e7c7370SDerryint    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
4986e7c7370SDerrycJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item) item--,c=c->next; return c;}
4996e7c7370SDerrycJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object->child; while (c && strcasecmp(c->string,string)) c=c->next; return c;}
5006e7c7370SDerry
5016e7c7370SDerry// Utility for array list handling.
5026e7c7370SDerrystatic void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
5036e7c7370SDerry
5046e7c7370SDerry// Add item to array/object.
5056e7c7370SDerryvoid   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);}}
5066e7c7370SDerryvoid   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);}
5076e7c7370SDerry
5086e7c7370SDerry// Create basic types:
5096e7c7370SDerrycJSON *cJSON_CreateNull()						{cJSON *item=cJSON_New_Item();item->type=cJSON_NULL;return item;}
5106e7c7370SDerrycJSON *cJSON_CreateTrue()						{cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;}
5116e7c7370SDerrycJSON *cJSON_CreateFalse()						{cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;}
5126e7c7370SDerrycJSON *cJSON_CreateNumber(int num)			{cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valueint=(int)num;return item;}
5136e7c7370SDerrycJSON *cJSON_CreateString(const char *string)	{cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;}
5146e7c7370SDerrycJSON *cJSON_CreateArray()						{cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;}
5156e7c7370SDerrycJSON *cJSON_CreateObject()						{cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;}
5166e7c7370SDerry
5176e7c7370SDerry// Create Arrays:
5186e7c7370SDerrycJSON *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;}
5196e7c7370SDerrycJSON *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;}
520