cJSON.c revision 18728fe0
1/*
2  Copyright (c) 2009 Dave Gamble
3
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21*/
22
23// cJSON
24// JSON parser in C.
25
26#if 0
27#include <string.h>
28#include <stdio.h>
29#include <math.h>
30#include <stdlib.h>
31#include <float.h>
32#endif
33
34#include "cJSON.h"
35
36#include <linux/module.h>
37#include <linux/slab.h>
38
39#if 0
40#if defined(WINDOWS) || defined(__WIN32__) || defined(WIN32) || defined(_WIN32)
41#define strcasecmp stricmp
42#define strdup _strdup
43#endif
44#endif
45
46
47#if 0
48static void *(*cJSON_malloc)(size_t sz) = malloc;
49static void *(*cJSON_realloc)(void *ptr, size_t sz) = realloc;
50static void (*cJSON_free)(void *ptr) = free;
51#endif
52
53static void *cJSON_malloc(size_t sz) {
54	return kmalloc(sz, GFP_KERNEL);
55}
56
57static void *cJSON_realloc(void *ptr, size_t sz)
58{
59	return krealloc(ptr, sz, GFP_KERNEL);
60}
61
62static void cJSON_free(void *ptr)
63{
64	 kfree(ptr);
65}
66
67static char* cJSON_strdup(const char* str)
68{
69      size_t len;
70      char* copy;
71
72      len = strlen(str) + 1;
73      if (!(copy = (char*)cJSON_malloc(len))) return 0;
74      memcpy(copy,str,len);
75      return copy;
76}
77
78#if 0
79void cJSON_InitHooks(cJSON_Hooks* hooks)
80{
81    if (!hooks) { /* Reset hooks */
82        cJSON_malloc = malloc;
83        cJSON_realloc = realloc;
84        cJSON_free = free;
85        return;
86    }
87
88	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
89	cJSON_realloc= (hooks->realloc_fn)?hooks->realloc_fn:realloc;
90	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
91}
92#endif
93
94// Internal constructor.
95static cJSON *cJSON_New_Item(void)
96{
97	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
98	if (node) memset(node,0,sizeof(cJSON));
99	return node;
100}
101
102// Delete a cJSON structure.
103void cJSON_Delete(cJSON *c)
104{
105	cJSON *next;
106	while (c)
107	{
108		next=c->next;
109		if (c->child) cJSON_Delete(c->child);
110		if (c->valuestring) cJSON_free(c->valuestring);
111		if (c->string) cJSON_free(c->string);
112		cJSON_free(c);
113		c=next;
114	}
115}
116
117
118/* Parse the input text to generate a number, and populate the result into item. */
119static const char *parse_number(cJSON *item,const char *num)
120{
121	int n=0,sign=1;
122
123	if (*num=='-') sign=-1,num++;	/* Has sign? */
124	if (*num=='0') num++;			/* is zero */
125	if (*num>='1' && *num<='9')	do	n=(n*10)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
126	item->valueint=(int)n;
127	item->type=cJSON_Number;
128	return num;
129}
130
131/* Render the number nicely from the given item into a string. */
132static char *print_number(cJSON *item)
133{
134	char *str;
135	str=(char*)cJSON_malloc(21);
136	if (str)
137		sprintf(str,"%d",item->valueint);
138	return str;
139}
140
141
142// Parse the input text into an unescaped cstring, and populate item.
143static const char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
144static const char *parse_string(cJSON *item,const char *str)
145{
146	const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
147	if (*str!='\"') return 0;	// not a string!
148
149	while (*ptr!='\"' && *ptr>31 && ++len) if (*ptr++ == '\\') ptr++;	// Skip escaped quotes.
150
151	out=(char*)cJSON_malloc(len+1);	// This is how long we need for the string, roughly.
152	if (!out) return 0;
153
154	ptr=str+1;ptr2=out;
155	while (*ptr!='\"' && *ptr>31)
156	{
157		if (*ptr!='\\') *ptr2++=*ptr++;
158		else
159		{
160			ptr++;
161			switch (*ptr)
162			{
163				case 'b': *ptr2++='\b';	break;
164				case 'f': *ptr2++='\f';	break;
165				case 'n': *ptr2++='\n';	break;
166				case 'r': *ptr2++='\r';	break;
167				case 't': *ptr2++='\t';	break;
168				case 'u':	 // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
169					sscanf(ptr+1,"%4x",&uc);	// get the unicode char.
170					len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
171
172					switch (len) {
173						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
174						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
175						case 1: *--ptr2 =(uc | firstByteMark[len]);
176					}
177					ptr2+=len;ptr+=4;
178					break;
179				default:  *ptr2++=*ptr; break;
180			}
181			ptr++;
182		}
183	}
184	*ptr2=0;
185	if (*ptr=='\"') ptr++;
186	item->valuestring=out;
187	item->type=cJSON_String;
188	return ptr;
189}
190
191// Render the cstring provided to an escaped version that can be printed.
192static char *print_string_ptr(const char *str)
193{
194	const char *ptr;char *ptr2,*out;int len=0;
195
196	ptr=str;while (*ptr && ++len) {if (*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
197
198	out=(char*)cJSON_malloc(len+3);
199	ptr2=out;ptr=str;
200	*ptr2++='\"';
201	while (*ptr)
202	{
203		if (*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
204		else
205		{
206			*ptr2++='\\';
207			switch (*ptr++)
208			{
209				case '\\':	*ptr2++='\\';	break;
210				case '\"':	*ptr2++='\"';	break;
211				case '\b':	*ptr2++='b';	break;
212				case '\f':	*ptr2++='f';	break;
213				case '\n':	*ptr2++='n';	break;
214				case '\r':	*ptr2++='r';	break;
215				case '\t':	*ptr2++='t';	break;
216				default: ptr2--;	break;	// eviscerate with prejudice.
217			}
218		}
219	}
220	*ptr2++='\"';*ptr2++=0;
221	return out;
222}
223// Invote print_string_ptr (which is useful) on an item.
224static char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}
225
226// Predeclare these prototypes.
227static const char *parse_value(cJSON *item,const char *value);
228static char *print_value(cJSON *item,int depth);
229static const char *parse_array(cJSON *item,const char *value);
230static char *print_array(cJSON *item,int depth);
231static const char *parse_object(cJSON *item,const char *value);
232static char *print_object(cJSON *item,int depth);
233
234// Utility to jump whitespace and cr/lf
235static const char *skip(const char *in) {while (in && *in<=32) in++; return in;}
236
237// Parse an object - create a new root, and populate.
238cJSON *cJSON_Parse(const char *value)
239{
240	cJSON *c=cJSON_New_Item();
241	if (!c) return 0;       /* memory fail */
242
243	if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
244	return c;
245}
246
247// Render a cJSON item/entity/structure to text.
248char *cJSON_Print(cJSON *item)			{return print_value(item,0);}
249
250// Parser core - when encountering text, process appropriately.
251static const char *parse_value(cJSON *item,const char *value)
252{
253	if (!value)						return 0;	// Fail on null.
254	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
255	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
256	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
257	if (*value=='\"')				{ return parse_string(item,value); }
258	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
259	if (*value=='[')				{ return parse_array(item,value); }
260	if (*value=='{')				{ return parse_object(item,value); }
261
262	return 0;	// failure.
263}
264
265// Render a value to text.
266static char *print_value(cJSON *item,int depth)
267{
268	char *out=0;
269	switch (item->type)
270	{
271		case cJSON_NULL:	out=cJSON_strdup("null");	break;
272		case cJSON_False:	out=cJSON_strdup("false");break;
273		case cJSON_True:	out=cJSON_strdup("true"); break;
274		case cJSON_Number:	out=print_number(item);break;
275		case cJSON_String:	out=print_string(item);break;
276		case cJSON_Array:	out=print_array(item,depth);break;
277		case cJSON_Object:	out=print_object(item,depth);break;
278	}
279	return out;
280}
281
282// Build an array from input text.
283static const char *parse_array(cJSON *item,const char *value)
284{
285	cJSON *child;
286	if (*value!='[')	return 0;	// not an array!
287
288	item->type=cJSON_Array;
289	value=skip(value+1);
290	if (*value==']') return value+1;	// empty array.
291
292	item->child=child=cJSON_New_Item();
293	if (!item->child) return 0;		 // memory fail
294	value=skip(parse_value(child,skip(value)));	// skip any spacing, get the value.
295	if (!value) return 0;
296
297	while (*value==',')
298	{
299		cJSON *new_item;
300		if (!(new_item=cJSON_New_Item())) return 0; 	// memory fail
301		child->next=new_item;new_item->prev=child;child=new_item;
302		value=skip(parse_value(child,skip(value+1)));
303		if (!value) return 0;	// memory fail
304	}
305
306	if (*value==']') return value+1;	// end of array
307	return 0;	// malformed.
308}
309
310// Render an array to text
311static char *print_array(cJSON *item,int depth)
312{
313	char *out,*ptr,*ret;int len=5;
314	cJSON *child=item->child;
315
316	out=(char*)cJSON_malloc(len);*out='[';
317	ptr=out+1;*ptr=0;
318	while (child)
319	{
320		ret=print_value(child,depth+1);
321		if (!ret) {cJSON_free(out);return 0;}	// Check for failure!
322		len+=strlen(ret)+3;
323		out=(char*)cJSON_realloc(out,len);
324		ptr=out+strlen(out);
325		ptr+=sprintf(ptr,ret);
326		if (child->next) {*ptr++=',';*ptr++=' ';*ptr=0;}
327		child=child->next;
328		cJSON_free(ret);
329	}
330	*ptr++=']';*ptr++=0;
331	return out;
332}
333
334// Build an object from the text.
335static const char *parse_object(cJSON *item,const char *value)
336{
337	cJSON *child;
338	if (*value!='{')	return 0;	// not an object!
339
340	item->type=cJSON_Object;
341	value=skip(value+1);
342	if (*value=='}') return value+1;	// empty array.
343
344	item->child=child=cJSON_New_Item();
345	value=skip(parse_string(child,skip(value)));
346	if (!value) return 0;
347	child->string=child->valuestring;child->valuestring=0;
348	if (*value!=':') return 0;	// fail!
349	value=skip(parse_value(child,skip(value+1)));	// skip any spacing, get the value.
350	if (!value) return 0;
351
352	while (*value==',')
353	{
354		cJSON *new_item;
355		if (!(new_item=cJSON_New_Item()))	return 0; // memory fail
356		child->next=new_item;new_item->prev=child;child=new_item;
357		value=skip(parse_string(child,skip(value+1)));
358		if (!value) return 0;
359		child->string=child->valuestring;child->valuestring=0;
360		if (*value!=':') return 0;	// fail!
361		value=skip(parse_value(child,skip(value+1)));	// skip any spacing, get the value.
362		if (!value) return 0;
363	}
364
365	if (*value=='}') return value+1;	// end of array
366	return 0;	// malformed.
367}
368
369// Render an object to text.
370static char *print_object(cJSON *item,int depth)
371{
372	char *out,*ptr,*ret,*str;int len=7,i;
373	cJSON *child=item->child;
374
375	depth++;len+=depth;out=(char*)cJSON_malloc(len);*out='{';
376	ptr=out+1;*ptr++='\n';*ptr=0;
377	while (child)
378	{
379		str=print_string_ptr(child->string);
380		if (!str) {cJSON_free(out);return 0;}
381		ret=print_value(child,depth);
382		if (!ret) {cJSON_free(str);cJSON_free(out);return 0;}	// Check for failure!
383		len+=strlen(ret)+strlen(str)+4+depth;
384		out=(char*)cJSON_realloc(out,len);
385		ptr=out+strlen(out);
386		for (i=0;i<depth;i++) *ptr++='\t';
387		ptr+=sprintf(ptr,str);
388		*ptr++=':';*ptr++='\t';
389		ptr+=sprintf(ptr,ret);
390		if (child->next) *ptr++=',';
391		*ptr++='\n';*ptr=0;
392		child=child->next;
393		cJSON_free(str);cJSON_free(ret);
394	}
395	for (i=0;i<depth-1;i++) *ptr++='\t';
396	*ptr++='}';*ptr++=0;
397	return out;
398}
399#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
400
401static void skip_oneline_comment(char **input)
402{
403    *input += static_strlen("//");
404
405    for (; (*input)[0] != '\0'; ++(*input))
406    {
407        if ((*input)[0] == '\n') {
408            *input += static_strlen("\n");
409            return;
410        }
411    }
412}
413static void skip_multiline_comment(char **input)
414{
415    *input += static_strlen("/*");
416
417    for (; (*input)[0] != '\0'; ++(*input))
418    {
419        if (((*input)[0] == '*') && ((*input)[1] == '/'))
420        {
421            *input += static_strlen("*/");
422            return;
423        }
424    }
425}
426static void minify_string(char **input, char **output) {
427    (*output)[0] = (*input)[0];
428    *input += static_strlen("\"");
429    *output += static_strlen("\"");
430
431
432    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
433        (*output)[0] = (*input)[0];
434
435        if ((*input)[0] == '\"') {
436            (*output)[0] = '\"';
437            *input += static_strlen("\"");
438            *output += static_strlen("\"");
439            return;
440        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
441            (*output)[1] = (*input)[1];
442            *input += static_strlen("\"");
443            *output += static_strlen("\"");
444        }
445    }
446}
447
448void cJSON_Minify(char *json)
449{
450    char *into = json;
451
452    if (json == NULL)
453    {
454        return;
455    }
456
457    while (json[0] != '\0')
458    {
459        switch (json[0])
460        {
461            case ' ':
462            case '\t':
463            case '\r':
464            case '\n':
465                json++;
466                break;
467
468            case '/':
469                if (json[1] == '/')
470                {
471                    skip_oneline_comment(&json);
472                }
473                else if (json[1] == '*')
474                {
475                    skip_multiline_comment(&json);
476                } else {
477                    json++;
478                }
479                break;
480
481            case '\"':
482                minify_string(&json, (char**)&into);
483                break;
484
485            default:
486                into[0] = json[0];
487                json++;
488                into++;
489        }
490    }
491
492    /* and null-terminate. */
493    *into = '\0';
494}
495
496// Get Array size/item / object item.
497int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
498cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item) item--,c=c->next; return c;}
499cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object->child; while (c && strcasecmp(c->string,string)) c=c->next; return c;}
500
501// Utility for array list handling.
502static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
503
504// Add item to array/object.
505void   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);}}
506void   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);}
507
508// Create basic types:
509cJSON *cJSON_CreateNull()						{cJSON *item=cJSON_New_Item();item->type=cJSON_NULL;return item;}
510cJSON *cJSON_CreateTrue()						{cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;}
511cJSON *cJSON_CreateFalse()						{cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;}
512cJSON *cJSON_CreateNumber(int num)			{cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valueint=(int)num;return item;}
513cJSON *cJSON_CreateString(const char *string)	{cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;}
514cJSON *cJSON_CreateArray()						{cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;}
515cJSON *cJSON_CreateObject()						{cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;}
516
517// Create Arrays:
518cJSON *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;}
519cJSON *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