/*
* ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
* │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐
* └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
* │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
* │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
* │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤
* │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │
* ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
* │ Ctrl│ │Alt │ Space │ Alt│ │ │Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│
* └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
* @Description:
* @Version: 1.0
* @Autor: NelsonYoung
* @Date: 2021-10-02 15:08:02
*/#ifndefcJSON__c#definecJSON__c/*===========================================================================
* Header file
*===========================================================================*/#include<string.h>#include<stdio.h>#include<math.h>#include<stdlib.h>#include<float.h>#include<limits.h>#include<ctype.h>#include"cJSON.h"/*===========================================================================
* DEFINITION
*==========================================================================*//* Parse the input text into an unescaped cstring, and populate item. */staticconstunsignedchar firstByteMark[7]={0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFC};/*===========================================================================
* Global variable
*==========================================================================*/void*Lifesense_mem_alloc(uint32_t sz){returnmalloc(sz);}voidLifesense_mem_free(void*ptr){free(ptr);}uint32_tmemscpy(void*dst,uint32_t dst_size,constvoid*src,uint32_t src_size){uint32_t copy_size =(dst_size <= src_size)? dst_size : src_size;memcpy(dst, src, copy_size);return copy_size;}staticconstchar*ep;/*===========================================================================
* FUNCTION
*==========================================================================*//**
* @description:
* @param {*}
* @return {*}
* @author: NelsonYoung
*/constchar*cJSON_GetErrorPtr(void){return ep;}/**
* @description:
* @param {int} c
* @return {*}
* @author: NelsonYoung
*/staticintcJSON_isupper(int c){return'A'<= c && c <='Z';}/**
* @description:
* @param {int} c
* @return {*}
* @author: NelsonYoung
*/staticintcJSON_tolower(int c){returncJSON_isupper(c)? c +('a'-'A'): c;}/**
* @description:
* @param {char} *s1
* @param {char} *s2
* @return {*}
* @author: NelsonYoung
*/staticintcJSON_strcasecmp(constchar*s1,constchar*s2){if(!s1){return(s1 == s2)?0:1;}if(!s2){return1;}for(;cJSON_tolower(*s1)==cJSON_tolower(*s2);++s1,++s2)if(*s1 ==0){return0;}returncJSON_tolower(*(constunsignedchar*)s1)-cJSON_tolower(*(constunsignedchar*)s2);}staticvoid*(*cJSON_malloc)(size_t sz)= Lifesense_mem_alloc;staticvoid(*cJSON_free)(void*ptr)= Lifesense_mem_free;/**
* @description:
* @param {char} *str
* @return {*}
* @author: NelsonYoung
*/staticchar*cJSON_strdup(constchar*str){size_t len;char*copy;if(!str){return0;}
len =strlen(str)+1;
copy =(char*)cJSON_malloc(len);if(!copy){return0;}memscpy(copy, len, str, len);return copy;}/**
* @description:
* @param {cJSON_Hooks} *hooks
* @return {*}
* @author: NelsonYoung
*/voidcJSON_InitHooks(cJSON_Hooks *hooks){if(!hooks)/* Reset hooks */{
cJSON_malloc = malloc;
cJSON_free = free;return;}
cJSON_malloc =(hooks->malloc_fn)? hooks->malloc_fn : malloc;
cJSON_free =(hooks->free_fn)? hooks->free_fn : free;}/* Internal constructor. *//**
* @description:
* @param {*}
* @return {*}
* @author: NelsonYoung
*/static cJSON *cJSON_New_Item(void){
cJSON *node =(cJSON *)cJSON_malloc(sizeof(cJSON));if(node){memset(node,0,sizeof(cJSON));}return node;}/* Delete a cJSON structure. */voidcJSON_Delete(cJSON *c){
cJSON *next;while(c){
next = c->next;if(!(c->type & cJSON_IsReference)&& c->child){cJSON_Delete(c->child);}if(!(c->type & cJSON_IsReference)&& c->valuestring){cJSON_free(c->valuestring);}if(c->string){cJSON_free(c->string);}cJSON_free(c);
c = next;}}/* Parse the input text to generate a number, and populate the result into item.
*//**
* @description:
* @param {cJSON} *item
* @param {char} *num
* @return {*}
* @author: NelsonYoung
*/staticconstchar*parse_number(cJSON *item,constchar*num){double n =0, sign =1, scale =0;int subscale =0, signsubscale =1;if(*num =='-'){ sign =-1, num++;}/* Has sign? */if(*num =='0'){ num++;}/* is zero */if(*num >='1'&&*num <='9')do{ n =(n *10.0)+(*num++-'0');}while(*num >='0'&&*num <='9');/* Number? */if(*num =='.'&& num[1]>='0'&& num[1]<='9'){
num++;do{ n =(n *10.0)+(*num++-'0'), scale--;}while(*num >='0'&&*num <='9');}/* Fractional part? */if(*num =='e'||*num =='E')/* Exponent? */{
num++;if(*num =='+'){ num++;}elseif(*num =='-'){ signsubscale =-1, num++;}/* With sign? */while(*num >='0'&&*num <='9'){ subscale =(subscale *10)+(*num++-'0');}/* Number? */}
n = sign * n *pow(10.0,(scale + subscale * signsubscale));/* number = +/-number.fraction *10^+/- exponent */
item->valuedouble = n;
item->valueint =(int)n;
item->type = cJSON_Number;return num;}/* Render the number nicely from the given item into a string. *//**
* @description:
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/staticchar*print_number(cJSON *item){char*str;double d = item->valuedouble;//由于MA510编译器不支持浮点数格式化输出,类型参数中增加小数位数参数用于处理小数显示if(item->valueplaces){
str =(char*)cJSON_malloc(64);/* This is a nice tradeoff. */if(str){int factor =(int)pow(10, item->valueplaces);if(item->valueplaces){snprintf(str,64,"%d.%0*d", item->valueint / factor, item->valueplaces,abs(item->valueint)% factor);}else{snprintf(str,64,"%f", d);}}}elseif(fabs(((double)item->valueint)- d)<= DBL_EPSILON && d <= INT_MAX &&
d >= INT_MIN){
str =(char*)cJSON_malloc(21);/* 2^64+1 can be represented in 21 chars. */if(str){snprintf(str,21,"%d", item->valueint);}}else{
str =(char*)cJSON_malloc(64);/* This is a nice tradeoff. */if(str){if(fabs(floor(d)- d)<= DBL_EPSILON &&fabs(d)<1.0e60){snprintf(str,64,"%.0f", d);}elseif(fabs(d)<1.0e-6||fabs(d)>1.0e9){snprintf(str,64,"%e", d);}else{snprintf(str,64,"%f", d);}}}return str;}/**
* @description:
* @param {char} *str
* @return {*}
* @author: NelsonYoung
*/staticunsignedparse_hex4(constchar*str){unsigned h =0;if(*str >='0'&&*str <='9'){ h +=(*str)-'0';}elseif(*str >='A'&&*str <='F'){ h +=10+(*str)-'A';}elseif(*str >='a'&&*str <='f'){ h +=10+(*str)-'a';}else{return0;}
h = h <<4;
str++;if(*str >='0'&&*str <='9'){ h +=(*str)-'0';}elseif(*str >='A'&&*str <='F'){ h +=10+(*str)-'A';}elseif(*str >='a'&&*str <='f'){ h +=10+(*str)-'a';}else{return0;}
h = h <<4;
str++;if(*str >='0'&&*str <='9'){ h +=(*str)-'0';}elseif(*str >='A'&&*str <='F'){ h +=10+(*str)-'A';}elseif(*str >='a'&&*str <='f'){ h +=10+(*str)-'a';}else{return0;}
h = h <<4;
str++;if(*str >='0'&&*str <='9'){ h +=(*str)-'0';}elseif(*str >='A'&&*str <='F'){ h +=10+(*str)-'A';}elseif(*str >='a'&&*str <='f'){ h +=10+(*str)-'a';}else{return0;}return h;}/**
* @description:
* @param {cJSON} *item
* @param {char} *str
* @return {*}
* @author: NelsonYoung
*/staticconstchar*parse_string(cJSON *item,constchar*str){constchar*ptr = str +1;char*ptr2;char*out;int len =0;unsigned uc, uc2;if(*str !='\"'){
ep = str;return0;}/* not a string! */while(*ptr !='\"'&&*ptr &&++len)if(*ptr++=='\\'){ ptr++;}/* Skip escaped quotes. */
out =(char*)cJSON_malloc(
len +1);/* This is how long we need for the string, roughly. */if(!out){return0;}
ptr = str +1;
ptr2 = out;while(*ptr !='\"'&&*ptr){if(*ptr !='\\'){*ptr2++=*ptr++;}else{
ptr++;switch(*ptr){case'b':*ptr2++='\b';break;case'f':*ptr2++='\f';break;case'n':*ptr2++='\n';break;case'r':*ptr2++='\r';break;case't':*ptr2++='\t';break;case'u':/* transcode utf16 to utf8. */
uc =parse_hex4(ptr +1);
ptr +=4;/* get the unicode char. */if((uc >=0xDC00&& uc <=0xDFFF)|| uc ==0){break;}/* check for invalid. */if(uc >=0xD800&& uc <=0xDBFF)/* UTF16 surrogate pairs. */{if((ptr[1]!='\\')||(ptr[2]!='u')){break;}/* missing second-half of surrogate. */
uc2 =parse_hex4(ptr +3);
ptr +=6;if((uc2 <0xDC00)||(uc2 >0xDFFF)){break;}/* invalid second-half of surrogate. */
uc =0x10000+(((uc &0x3FF)<<10)|(uc2 &0x3FF));}
len =4;if(uc <0x80){ len =1;}elseif(uc <0x800){ len =2;}elseif(uc <0x10000){ len =3;}
ptr2 += len;switch(len){case4:*--ptr2 =((uc |0x80)&0xBF);
uc >>=6;case3:*--ptr2 =((uc |0x80)&0xBF);
uc >>=6;case2:*--ptr2 =((uc |0x80)&0xBF);
uc >>=6;case1:*--ptr2 =(uc | firstByteMark[len]);}
ptr2 += len;break;default:*ptr2++=*ptr;break;}
ptr++;}}*ptr2 =0;if(*ptr =='\"'){ ptr++;}
item->valuestring = out;
item->type = cJSON_String;return ptr;}/* Render the cstring provided to an escaped version that can be printed. *//**
* @description:
* @param {char} *str
* @return {*}
* @author: NelsonYoung
*/staticchar*print_string_ptr(constchar*str){constchar*ptr;char*ptr2,*out;int len =0;int len_avalible =0;unsignedchar token;if(!str){returncJSON_strdup("");}
ptr = str;
token =*ptr;while((token)&&++len){if(strchr("\"\\\b\f\n\r\t", token)){ len++;}elseif(token <32){ len +=5;}
ptr++;
token =*ptr;}
out =(char*)cJSON_malloc(len +3);if(!out){return0;}
len_avalible = len +3;
ptr2 = out;
ptr = str;*ptr2++='\"';
len_avalible--;while(*ptr){if((unsignedchar)*ptr >31&&*ptr !='\"'&&*ptr !='\\'){*ptr2++=*ptr++;
len_avalible--;}else{*ptr2++='\\';
len_avalible--;switch(token =*ptr++){case'\\':*ptr2++='\\';
len_avalible--;break;case'\"':*ptr2++='\"';
len_avalible--;break;case'\b':*ptr2++='b';
len_avalible--;break;case'\f':*ptr2++='f';
len_avalible--;break;case'\n':*ptr2++='n';
len_avalible--;break;case'\r':*ptr2++='r';
len_avalible--;break;case'\t':*ptr2++='t';
len_avalible--;break;default:// snprintf(ptr2, len + 3, "u%04x", token);snprintf(ptr2, len_avalible,"u%04x", token);
ptr2 +=5;
len_avalible -=5;break;/* escape and print */}}}*ptr2++='\"';*ptr2++=0;return out;}/* Invote print_string_ptr (which is useful) on an item. *//**
* @description:
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/staticchar*print_string(cJSON *item){returnprint_string_ptr(item->valuestring);}/* Predeclare these prototypes. */staticconstchar*parse_value(cJSON *item,constchar*value);staticchar*print_value(cJSON *item,int depth,int fmt);staticconstchar*parse_array(cJSON *item,constchar*value);staticchar*print_array(cJSON *item,int depth,int fmt);staticconstchar*parse_object(cJSON *item,constchar*value);staticchar*print_object(cJSON *item,int depth,int fmt);/* Utility to jump whitespace and cr/lf *//**
* @description:
* @param {char} *in
* @return {*}
* @author: NelsonYoung
*/staticconstchar*skip(constchar*in){while(in &&*in &&(unsignedchar)*in <=32){ in++;}return in;}/* Parse an object - create a new root, and populate. *//**
* @description:
* @param {*}
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_ParseWithOpts(constchar*value,constchar**return_parse_end,int require_null_terminated){constchar*end =0;
cJSON *c =cJSON_New_Item();
ep =0;if(!c){return0;}/* memory fail */
end =parse_value(c,skip(value));if(!end){cJSON_Delete(c);return0;}/* parse failure. ep is set. *//* if we require null-terminated JSON without appended garbage, skip and
* then check for a null terminator */if(require_null_terminated){
end =skip(end);if(*end){cJSON_Delete(c);
ep = end;return0;}}if(return_parse_end){*return_parse_end = end;}return c;}/* Default options for cJSON_Parse *//**
* @description:
* @param {char} *value
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_Parse(constchar*value){returncJSON_ParseWithOpts(value,0,0);}/* Render a cJSON item/entity/structure to text. *//**
* @description:
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/char*cJSON_Print(cJSON *item){returnprint_value(item,0,1);}/**
* @description:
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/char*cJSON_PrintUnformatted(cJSON *item){returnprint_value(item,0,0);}/* Parser core - when encountering text, process appropriately. *//**
* @description:
* @param {cJSON} *item
* @param {char} *value
* @return {*}
* @author: NelsonYoung
*/staticconstchar*parse_value(cJSON *item,constchar*value){if(!value){return0;}/* Fail on null. */if(!strncmp(value,"null",4)){
item->type = cJSON_NULL;return value +4;}if(!strncmp(value,"false",5)){
item->type = cJSON_False;return value +5;}if(!strncmp(value,"true",4)){
item->type = cJSON_True;
item->valueint =1;return value +4;}if(*value =='\"'){returnparse_string(item, value);}if(*value =='-'||(*value >='0'&&*value <='9')){returnparse_number(item, value);}if(*value =='['){returnparse_array(item, value);}if(*value =='{'){returnparse_object(item, value);}
ep = value;return0;/* failure. */}/* Render a value to text. *//**
* @description:
* @param {cJSON} *item
* @param {int} depth
* @param {int} fmt
* @return {*}
* @author: NelsonYoung
*/staticchar*print_value(cJSON *item,int depth,int fmt){char*out =0;if(!item){return0;}switch((item->type)&255){case cJSON_NULL:
out =cJSON_strdup("null");break;case cJSON_False:
out =cJSON_strdup("false");break;case cJSON_True:
out =cJSON_strdup("true");break;case cJSON_Number:
out =print_number(item);break;case cJSON_String:
out =print_string(item);break;case cJSON_Array:
out =print_array(item, depth, fmt);break;case cJSON_Object:
out =print_object(item, depth, fmt);break;}return out;}/* Build an array from input text. *//**
* @description:
* @param {cJSON} *item
* @param {char} *value
* @return {*}
* @author: NelsonYoung
*/staticconstchar*parse_array(cJSON *item,constchar*value){
cJSON *child;if(*value !='['){
ep = value;return0;}/* not an array! */
item->type = cJSON_Array;
value =skip(value +1);if(*value ==']'){return value +1;}/* empty array. */
item->child = child =cJSON_New_Item();if(!item->child){return0;}/* memory fail */
value =skip(parse_value(child,skip(value)));/* skip any spacing, get the value. */if(!value){return0;}while(*value ==','){
cJSON *new_item =cJSON_New_Item();if(!new_item){return0;}/* memory fail */
child->next = new_item;
new_item->prev = child;
child = new_item;
value =skip(parse_value(child,skip(value +1)));if(!value){return0;}/* memory fail */}if(*value ==']'){return value +1;}/* end of array */
ep = value;return0;/* malformed. */}/* Render an array to text *//**
* @description:
* @param {cJSON} *item
* @param {int} depth
* @param {int} fmt
* @return {*}
* @author: NelsonYoung
*/staticchar*print_array(cJSON *item,int depth,int fmt){char**entries;char*out =0,*ptr,*ret;int len =5;
cJSON *child = item->child;int numentries =0, i =0, fail =0;/* How many entries in the array? */while(child){ numentries++, child = child->next;}/* Explicitly handle numentries==0 */if(!numentries){
out =(char*)cJSON_malloc(3);if(out){strlcpy(out,"[]",3);}return out;}/* Allocate an array to hold the values for each */
entries =(char**)cJSON_malloc(numentries *sizeof(char*));if(!entries){return0;}memset(entries,0, numentries *sizeof(char*));/* Retrieve all the results: */
child = item->child;while(child &&!fail){
ret =print_value(child, depth +1, fmt);
entries[i++]= ret;if(ret){ len +=strlen(ret)+2+(fmt ?1:0);}else{ fail =1;}
child = child->next;}/* If we didn't fail, try to malloc the output string */if(!fail){ out =(char*)cJSON_malloc(len);}/* If that fails, we fail. */if(!out){ fail =1;}/* Handle failure. */if(fail){for(i =0; i < numentries; i++)if(entries[i]){cJSON_free(entries[i]);}cJSON_free(entries);return0;}/* Compose the output array. */*out ='[';
ptr = out +1;*ptr =0;for(i =0; i < numentries; i++){strlcpy(ptr, entries[i],(strlen(entries[i])+1));
ptr +=strlen(entries[i]);if(i != numentries -1){*ptr++=',';if(fmt){*ptr++=' ';}*ptr =0;}cJSON_free(entries[i]);}cJSON_free(entries);*ptr++=']';*ptr++=0;return out;}/* Build an object from the text. *//**
* @description:
* @param {cJSON} *item
* @param {char} *value
* @return {*}
* @author: NelsonYoung
*/staticconstchar*parse_object(cJSON *item,constchar*value){
cJSON *child;
cJSON *new_item;if(*value !='{'){
ep = value;return0;}/* not an object! */
item->type = cJSON_Object;
value =skip(value +1);if(*value =='}'){return value +1;}/* empty array. */
item->child = child =cJSON_New_Item();if(!item->child){return0;}
value =skip(parse_string(child,skip(value)));if(!value){return0;}
child->string = child->valuestring;
child->valuestring =0;if(*value !=':'){
ep = value;return0;}/* fail! */
value =skip(parse_value(child,skip(value +1)));/* skip any spacing, get the value. */if(!value){return0;}while(*value ==','){constchar*c_str = value +1;while(1){if(*c_str ==0){
ep = value;return0;}/* fail! */if(*c_str =='}'){return c_str +1;/* end of array */}if((unsignedchar)*c_str >32){break;}
c_str++;}
new_item =cJSON_New_Item();if(!new_item){return0;}/* memory fail */
child->next = new_item;
new_item->prev = child;
child = new_item;
value =skip(parse_string(child,skip(value +1)));if(!value){return0;}
child->string = child->valuestring;
child->valuestring =0;if(*value !=':'){
ep = value;return0;}/* fail! */
value =skip(parse_value(child,skip(value +1)));/* skip any spacing, get the value. */if(!value){return0;}}if(*value =='}'){return value +1;}/* end of array */
ep = value;return0;/* malformed. */}/* Render an object to text. *//**
* @description:
* @param {cJSON} *item
* @param {int} depth
* @param {int} fmt
* @return {*}
* @author: NelsonYoung
*/staticchar*print_object(cJSON *item,int depth,int fmt){char**entries =0,**names =0;char*out =0,*ptr,*ret,*str;int len =7, i =0, j;
cJSON *child = item->child;int numentries =0, fail =0;/* Count the number of entries. */while(child){ numentries++, child = child->next;}/* Explicitly handle empty object case */if(!numentries){
out =(char*)cJSON_malloc(fmt ? depth +4:3);if(!out){return0;}
ptr = out;*ptr++='{';if(fmt){*ptr++='\n';for(i =0; i < depth -1; i++){*ptr++='\t';}}*ptr++='}';*ptr++=0;return out;}/* Allocate space for the names and the objects */
entries =(char**)cJSON_malloc(numentries *sizeof(char*));if(!entries){return0;}
names =(char**)cJSON_malloc(numentries *sizeof(char*));if(!names){cJSON_free(entries);return0;}memset(entries,0,sizeof(char*)* numentries);memset(names,0,sizeof(char*)* numentries);/* Collect all the results into our arrays: */
child = item->child;
depth++;if(fmt){ len += depth;}while(child){
names[i]= str =print_string_ptr(child->string);
entries[i++]= ret =print_value(child, depth, fmt);if(str && ret){ len +=strlen(ret)+strlen(str)+2+(fmt ?2+ depth :0);}else{ fail =1;}
child = child->next;}/* Try to allocate the output string */if(!fail){ out =(char*)cJSON_malloc(len);}if(!out){ fail =1;}/* Handle failure */if(fail){for(i =0; i < numentries; i++){if(names[i]){cJSON_free(names[i]);}if(entries[i]){cJSON_free(entries[i]);}}cJSON_free(names);cJSON_free(entries);return0;}/* Compose the output: */*out ='{';
ptr = out +1;if(fmt){*ptr++='\n';}*ptr =0;for(i =0; i < numentries; i++){if(fmt){for(j =0; j < depth; j++){*ptr++='\t';}}strlcpy(ptr, names[i],(strlen(names[i])+1));
ptr +=strlen(names[i]);*ptr++=':';if(fmt){*ptr++='\t';}strlcpy(ptr, entries[i],(strlen(entries[i])+1));
ptr +=strlen(entries[i]);if(i != numentries -1){*ptr++=',';}if(fmt){*ptr++='\n';}*ptr =0;cJSON_free(names[i]);cJSON_free(entries[i]);}cJSON_free(names);cJSON_free(entries);if(fmt)for(i =0; i < depth -1; i++){*ptr++='\t';}*ptr++='}';*ptr++=0;return out;}/* Get Array size/item / object item. *//**
* @description:
* @param {cJSON} *array
* @return {*}
* @author: NelsonYoung
*/intcJSON_GetArraySize(cJSON *array){
cJSON *c = array->child;int i =0;while(c){ i++, c = c->next;}return i;}/**
* @description:
* @param {cJSON} *array
* @param {int} item
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_GetArrayItem(cJSON *array,int item){
cJSON *c = array->child;while(c && item >0){ item--, c = c->next;}return c;}/**
* @description:
* @param {cJSON} *object
* @param {char} *string
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_GetObjectItem(cJSON *object,constchar*string){
cJSON *c = object->child;while(c &&cJSON_strcasecmp(c->string, string)){ c = c->next;}return c;}/* Utility for array list handling. *//**
* @description:
* @param {cJSON} *prev
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/staticvoidsuffix_object(cJSON *prev, cJSON *item){
prev->next = item;
item->prev = prev;}/* Utility for handling references. *//**
* @description:
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/static cJSON *create_reference(cJSON *item){
cJSON *ref =cJSON_New_Item();if(!ref){return0;}memscpy(ref,sizeof(cJSON), item,sizeof(cJSON));
ref->string =0;
ref->type |= cJSON_IsReference;
ref->next = ref->prev =0;return ref;}/* Add item to array/object. *//**
* @description:
* @param {cJSON} *array
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/voidcJSON_AddItemToArray(cJSON *array, cJSON *item){
cJSON *c = array->child;if(!item){return;}if(!c){
array->child = item;}else{while(c && c->next){ c = c->next;}if(c){suffix_object(c, item);}}}/**
* @description:
* @param {cJSON} *object
* @param {char} *string
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/voidcJSON_AddItemToObject(cJSON *object,constchar*string, cJSON *item){if(!item){return;}if(item->string){cJSON_free(item->string);}
item->string =cJSON_strdup(string);cJSON_AddItemToArray(object, item);}/**
* @description:
* @param {cJSON} *array
* @param {cJSON} *item
* @return {*}
* @author: NelsonYoung
*/voidcJSON_AddItemReferenceToArray(cJSON *array, cJSON *item){cJSON_AddItemToArray(array,create_reference(item));}/**
* @description:
* @param {*}
* @return {*}
* @author: NelsonYoung
*/voidcJSON_AddItemReferenceToObject(cJSON *object,constchar*string,
cJSON *item){cJSON_AddItemToObject(object, string,create_reference(item));}/**
* @description:
* @param {cJSON} *array
* @param {int} which
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which){
cJSON *c = array->child;while(c && which >0){ c = c->next, which--;}if(!c){return0;}if(c->prev){ c->prev->next = c->next;}if(c->next){ c->next->prev = c->prev;}if(c == array->child){ array->child = c->next;}
c->prev = c->next =0;return c;}/**
* @description:
* @param {cJSON} *array
* @param {int} which
* @return {*}
* @author: NelsonYoung
*/voidcJSON_DeleteItemFromArray(cJSON *array,int which){cJSON_Delete(cJSON_DetachItemFromArray(array, which));}/**
* @description:
* @param {cJSON} *object
* @param {char} *string
* @return {*}
* @author: NelsonYoung
*/
cJSON *cJSON_DetachItemFromObject(cJSON *object,constchar*string){int i =0;
cJSON *c = object->child;while(c &&cJSON_strcasecmp(c->string, string)){ i++, c = c->next;}if(c){returncJSON_DetachItemFromArray(object, i);}return0;}/**
* @description:
* @param {cJSON} *object
* @param {char} *string
* @return {*}
* @author: NelsonYoung
*/voidcJSON_DeleteItemFromObject(cJSON *object,constchar*string){cJSON_Delete(cJSON_DetachItemFromObject(object, string));}/* Replace array/object items with new ones. *//**
* @description:
* @param {cJSON} *array
* @param {int} which
* @param {cJSON} *newitem
* @return {*}
* @author: NelsonYoung
*/voidcJSON_ReplaceItemInArray(cJSON *array,int which, cJSON *newitem){
cJSON *c = array->child;while(c && which >0){ c = c->next, which--;}if(!c){return;}
newitem->next = c->next;
newitem->prev = c->prev;if(newitem->next){ newitem->next->prev = newitem;}if(c == array->child){ array->child = newitem;}else{ newitem->prev->next = newitem;}
c->next = c->prev =0;cJSON_Delete(c);}voidcJSON_ReplaceItemInObject(cJSON *object,constchar*string,
cJSON *newitem){int i =0;
cJSON *c = object->child;while(c &&cJSON_strcasecmp(c->string, string)){ i++, c = c->next;}if(c){
newitem->string =cJSON_strdup(string);cJSON_ReplaceItemInArray(object, i, newitem);}}/* Create basic types: */
cJSON *cJSON_CreateNull(void){
cJSON *item =cJSON_New_Item();if(item){ item->type = cJSON_NULL;}return item;}
cJSON *cJSON_CreateTrue(void){
cJSON *item =cJSON_New_Item();if(item){ item->type = cJSON_True;}return item;}
cJSON *cJSON_CreateFalse(void){
cJSON *item =cJSON_New_Item();if(item){ item->type = cJSON_False;}return item;}
cJSON *cJSON_CreateBool(int b){
cJSON *item =cJSON_New_Item();if(item){ item->type = b ? cJSON_True : cJSON_False;}return item;}
cJSON *cJSON_CreateNumber(double num){
cJSON *item =cJSON_New_Item();if(item){
item->type = cJSON_Number;
item->valuedouble = num;
item->valueint =(int)num;}return item;}
cJSON *cJSON_CreateDouble(int decimal,int place){
cJSON *item =cJSON_New_Item();if(item){
item->type = cJSON_Number;
item->valuedouble =(double)decimal/pow(10, place);
item->valueint = decimal;
item->valueplaces = place;}return item;}
cJSON *cJSON_CreateString(constchar*string){
cJSON *item =cJSON_New_Item();if(item){
item->type = cJSON_String;
item->valuestring =cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void){
cJSON *item =cJSON_New_Item();if(item){ item->type = cJSON_Array;}return item;}
cJSON *cJSON_CreateObject(void){
cJSON *item =cJSON_New_Item();if(item){ item->type = cJSON_Object;}return item;}/* Create Arrays: */
cJSON *cJSON_CreateIntArray(constint*numbers,int count){int i;
cJSON *n =0,*p =0,*a =cJSON_CreateArray();for(i =0; a && i < count; i++){
n =cJSON_CreateNumber(numbers[i]);if(!i){ a->child = n;}else{suffix_object(p, n);}
p = n;}return a;}
cJSON *cJSON_CreateFloatArray(constfloat*numbers,int count){int i;
cJSON *n =0,*p =0,*a =cJSON_CreateArray();for(i =0; a && i < count; i++){
n =cJSON_CreateNumber(numbers[i]);if(!i){ a->child = n;}else{suffix_object(p, n);}
p = n;}return a;}
cJSON *cJSON_CreateDoubleArray(constdouble*numbers,int count){int i;
cJSON *n =0,*p =0,*a =cJSON_CreateArray();for(i =0; a && i < count; i++){
n =cJSON_CreateNumber(numbers[i]);if(!i){ a->child = n;}else{suffix_object(p, n);}
p = n;}return a;}
cJSON *cJSON_CreateStringArray(constchar**strings,int count){int i;
cJSON *n =0,*p =0,*a =cJSON_CreateArray();for(i =0; a && i < count; i++){
n =cJSON_CreateString(strings[i]);if(!i){ a->child = n;}else{suffix_object(p, n);}
p = n;}return a;}/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse){
cJSON *newitem,*cptr,*nptr =0,*newchild;/* Bail on bad ptr */if(!item){return0;}/* Create new item */
newitem =cJSON_New_Item();if(!newitem){return0;}/* Copy over all vars */
newitem->type = item->type &(~cJSON_IsReference),
newitem->valueint = item->valueint,
newitem->valuedouble = item->valuedouble;if(item->valuestring){
newitem->valuestring =cJSON_strdup(item->valuestring);if(!newitem->valuestring){cJSON_Delete(newitem);return0;}}if(item->string){
newitem->string =cJSON_strdup(item->string);if(!newitem->string){cJSON_Delete(newitem);return0;}}/* If non-recursive, then we're done! */if(!recurse){return newitem;}/* Walk the ->next chain for the child. */
cptr = item->child;while(cptr){
newchild =cJSON_Duplicate(cptr,1);/* Duplicate (with recurse) each item in the ->next chain */if(!newchild){cJSON_Delete(newitem);return0;}if(nptr){
nptr->next = newchild, newchild->prev = nptr;
nptr = newchild;}/* If newitem->child already set, then crosswire ->prev and ->next and
move on */else{
newitem->child = newchild;
nptr = newchild;}/* Set newitem->child and move to it */
cptr = cptr->next;}return newitem;}voidcJSON_Minify(char*json){char*into = json;while(*json){if(*json ==' '){ json++;}elseif(*json =='\t'){ json++;}// Whitespace characters.elseif(*json =='\r'){ json++;}elseif(*json =='\n'){ json++;}elseif((*json =='/')&&(json[1]=='/'))while(*json &&*json !='\n'){ json++;}// double-slash comments, to end of line.elseif((*json =='/')&&(json[1]=='*')){while(*json &&!(*json =='*'&& json[1]=='/')){ json++;}
json +=2;}// multiline comments.elseif(*json =='\"'){*into++=*json++;while(*json &&*json !='\"'){if(*json =='\\'){*into++=*json++;}*into++=*json++;}*into++=*json++;}// string literals, which are \" sensitive.else{*into++=*json++;}// All other characters.}*into =0;// and null-terminate.}#endif
头文件
/*
*
* ┏┓ ┏┓
* ┏┛┻━━━┛┻┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃ 神兽保佑
* ┃ ┃ 代码无bug
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
* @Description:
* @Version: 1.0
* @Autor: NelsonYoung
* @Date: 2021-10-02 15:34:51
*/#ifndefcJSON__h#definecJSON__h#ifdef__cplusplusextern"C"{#endif/*===========================================================================
* Header file
*===========================================================================*/#include<stdio.h>#include<stdlib.h>#include<ctype.h>#ifdefTARGET_LINUX#include<unistd.h>#endif/*TARGET_LINUX*/#include<limits.h>#include<string.h>#include<inttypes.h>/*===========================================================================
* DEFINITION
*===========================================================================*//* cJSON Types: */#definecJSON_False0#definecJSON_True1#definecJSON_NULL2#definecJSON_Number3#definecJSON_String4#definecJSON_Array5#definecJSON_Object6#definecJSON_IsReference256/* The cJSON structure: */typedefstructcJSON{structcJSON*next,*prev;/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */structcJSON*child;/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */int type;/* The type of the item, as above. */char*valuestring;/* The item's string, if type==cJSON_String */int valueint;/* The item's number, if type==cJSON_Number */double valuedouble;/* The item's number, if type==cJSON_Number */int valueplaces;/* The item's decimal places, if type==cJSON_Number and show in float*/char*string;/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */} cJSON;typedefstructcJSON_Hooks{void*(*malloc_fn)(size_t sz);void(*free_fn)(void*ptr);} cJSON_Hooks;/*===========================================================================
* Global variable
*===========================================================================*//*===========================================================================
* FUNCTION
*===========================================================================*//* Supply malloc, realloc and free functions to cJSON */externvoidcJSON_InitHooks(cJSON_Hooks *hooks);/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */extern cJSON *cJSON_Parse(constchar*value);/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */externchar*cJSON_Print(cJSON *item);/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */externchar*cJSON_PrintUnformatted(cJSON *item);/* Delete a cJSON entity and all subentities. */externvoidcJSON_Delete(cJSON *c);/* Returns the number of items in an array (or object). */externintcJSON_GetArraySize(cJSON *array);/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);/* Get item "string" from object. Case insensitive. */extern cJSON *cJSON_GetObjectItem(cJSON *object,constchar*string);/* For analysing failed parses. This returns a pointer to the parse error.
* You'll probably need to look a few chars back to make sense of it.
* Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */externconstchar*cJSON_GetErrorPtr(void);/* These calls create a cJSON item of the appropriate type. */extern cJSON *cJSON_CreateNull(void);extern cJSON *cJSON_CreateTrue(void);extern cJSON *cJSON_CreateFalse(void);extern cJSON *cJSON_CreateBool(int b);extern cJSON *cJSON_CreateNumber(double num);extern cJSON *cJSON_CreateDouble(int decimal,int place);extern cJSON *cJSON_CreateString(constchar*string);extern cJSON *cJSON_CreateArray(void);extern cJSON *cJSON_CreateObject(void);/* These utilities create an Array of count items. */extern cJSON *cJSON_CreateIntArray(constint*numbers,int count);extern cJSON *cJSON_CreateFloatArray(constfloat*numbers,int count);extern cJSON *cJSON_CreateDoubleArray(constdouble*numbers,int count);extern cJSON *cJSON_CreateStringArray(constchar**strings,int count);/* Append item to the specified array/object. */externvoidcJSON_AddItemToArray(cJSON *array, cJSON *item);externvoidcJSON_AddItemToObject(cJSON *object,constchar*string, cJSON *item);/* Append reference to item to the specified array/object.
* Use this when you want to add an existing cJSON to a new cJSON,
* but don't want to corrupt your existing cJSON. */externvoidcJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);externvoidcJSON_AddItemReferenceToObject(cJSON *object,constchar*string, cJSON *item);/* Remove/Detatch items from Arrays/Objects. */extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);externvoidcJSON_DeleteItemFromArray(cJSON *array,int which);extern cJSON *cJSON_DetachItemFromObject(cJSON *object,constchar*string);externvoidcJSON_DeleteItemFromObject(cJSON *object,constchar*string);/* Update array items. */externvoidcJSON_ReplaceItemInArray(cJSON *array,int which, cJSON *newitem);externvoidcJSON_ReplaceItemInObject(cJSON *object,constchar*string, cJSON *newitem);/* Duplicate a cJSON item */extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. *//* ParseWithOpts allows you to require (and check) that the JSON is null
* terminated, and to retrieve the pointer to the final byte parsed. */extern cJSON *cJSON_ParseWithOpts(constchar*value,constchar**return_parse_end,int require_null_terminated);externvoidcJSON_Minify(char*json);/* Macros for creating things quickly. */#definecJSON_AddNullToObject(object,name)cJSON_AddItemToObject(object, name,cJSON_CreateNull())#definecJSON_AddTrueToObject(object,name)cJSON_AddItemToObject(object, name,cJSON_CreateTrue())#definecJSON_AddFalseToObject(object,name)cJSON_AddItemToObject(object, name,cJSON_CreateFalse())#definecJSON_AddBoolToObject(object,name,b)cJSON_AddItemToObject(object, name,cJSON_CreateBool(b))#definecJSON_AddNumberToObject(object,name,n)cJSON_AddItemToObject(object, name,cJSON_CreateNumber(n))#definecJSON_AddStringToObject(object,name,s)cJSON_AddItemToObject(object, name,cJSON_CreateString(s))#definecJSON_AddDoubleToObject(object,name,d,p)cJSON_AddItemToObject(object, name,cJSON_CreateDouble(d,p))/* When assigning an integer value, it needs to be propagated to valuedouble too. */#definecJSON_SetIntValue(object,val)((object)?(object)->valueint=(object)->valuedouble=(val):(val))#ifdef__cplusplus}#endif#endif