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