这几天使用了一下JSON在STM32103平台上的使用,还是很好用的,在此记录下。 JSON是啥我也不总结了,就是直观的看起来是一个有格式的字符串,看起来非常清楚明白,有点像Python中的dicitionary的意思,实际使用的过程中主要就是“打包”和“解析”。下面直接来代码。 - char * Status_to_cJSON( char * cJSONROOM, ROBOStatus_TypeDef status)//传入一个变量的指针,这里cJSONROOM是一个全局变量(一个提前规定大小的字符数组),用来存放转换之后的JSON字符串
- {
- char *result;
- cJSON *root,*subroot;//新建两个cJSON的对象指针
- root=cJSON_CreateObject();//创建一个机器人状态的JSON对象
- subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象
- cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。
- cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);
- //同上
- cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);
- //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型
- cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);
- cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);
- cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);
- cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);
- cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);
- cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);
- cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);
- cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);
- cJSON_AddItemToObject(root, "RobotStatus", subroot);
- result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间
- strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量
- cJSON_Delete(root);//最后将root根节点删除
- myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃
- return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。
- }
复制代码注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。 - #include "malloc.h"
- //内存池(4字节对齐)
- __align(4) u8 membase[MEM_MAX_SIZE]; //内部SRAM内存池
- //内存管理表
- u16 memmapbase[MEM_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
- //内存管理参数
- const u32 memtblsize = MEM_ALLOC_TABLE_SIZE; //内存表大小
- const u32 memblksize = MEM_BLOCK_SIZE; //内存分块大小
- const u32 memsize = MEM_MAX_SIZE; //内存总大小
- //内存管理控制器
- struct _m_mallco_dev mallco_dev=
- {
- mem_init, //内存初始化
- mem_perused, //内存使用率
- membase, //内存池
- memmapbase, //内存管理状态表
- 0, //内存管理未就绪
- };
- //复制内存
- //*des:目的地址
- //*src:源地址
- //n:需要复制的内存长度(字节为单位)
- void mymemcpy(void *des,void *src,u32 n)
- {
- u8 *xdes=des;
- u8 *xsrc=src;
- while(n--)*xdes++=*xsrc++;
- }
- //设置内存
- //*s:内存首地址
- //c :要设置的值
- //count:需要设置的内存大小(字节为单位)
- void mymemset(void *s,u8 c,u32 count)
- {
- u8 *xs = s;
- while(count--)*xs++=c;
- }
- //内存管理初始化
- //memx:所属内存块
- void mem_init(void)
- {
- mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零
- mymemset(mallco_dev.membase, 0,memsize); //内存池所有数据清零
- mallco_dev.memrdy=1; //内存管理初始化OK
- }
- //获取内存使用率
- //memx:所属内存块
- //返回值:使用率(0~100)
- u8 mem_perused(void)
- {
- u32 used=0;
- u32 i;
- for(i=0;i<memtblsize;i++)
- {
- if(mallco_dev.memmap[i])used++;
- }
- return (used*100)/(memtblsize);
- }
- //内存分配(内部调用)
- //memx:所属内存块
- //size:要分配的内存大小(字节)
- //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
- u32 mem_malloc(u32 size)
- {
- signed long offset=0;
- u16 nmemb; //需要的内存块数
- u16 cmemb=0;//连续空内存块数
- u32 i;
- if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化
- if(size==0)return 0XFFFFFFFF;//不需要分配
- nmemb=size/memblksize; //获取需要分配的连续内存块数
- if(size%memblksize)nmemb++;
- for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区
- {
- if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加
- else cmemb=0; //连续内存块清零
- if(cmemb==nmemb) //找到了连续nmemb个空内存块
- {
- for(i=0;i<nmemb;i++) //标注内存块非空
- {
- mallco_dev.memmap[offset+i]=nmemb;
- }
- return (offset*memblksize);//返回偏移地址
- }
- }
- return 0XFFFFFFFF;//未找到符合分配条件的内存块
- }
- //释放内存(内部调用)
- //memx:所属内存块
- //offset:内存地址偏移
- //返回值:0,释放成功;1,释放失败;
- u8 mem_free(u32 offset)
- {
- int i;
- if(!mallco_dev.memrdy)//未初始化,先执行初始化
- {
- mallco_dev.init();
- return 1;//未初始化
- }
- if(offset<memsize)//偏移在内存池内.
- {
- int index=offset/memblksize; //偏移所在内存块号码
- int nmemb=mallco_dev.memmap[index]; //内存块数量
- for(i=0;i<nmemb;i++) //内存块清零
- {
- mallco_dev.memmap[index+i]=0;
- }
- return 0;
- }else return 2;//偏移超区了.
- }
- //释放内存(外部调用)
- //memx:所属内存块
- //ptr:内存首地址
- void myfree(void *ptr)
- {
- u32 offset;
- if(ptr==NULL)return;//地址为0.
- offset=(u32)ptr-(u32)mallco_dev.membase;
- mem_free(offset);//释放内存
- }
- //分配内存(外部调用)
- //memx:所属内存块
- //size:内存大小(字节)
- //返回值:分配到的内存首地址.
- void *mymalloc(u32 size)
- {
- u32 offset;
- offset=mem_malloc(size);
- if(offset==0XFFFFFFFF)return NULL;
- else return (void*)((u32)mallco_dev.membase+offset);
- }
- //重新分配内存(外部调用)
- //memx:所属内存块
- //*ptr:旧内存首地址
- //size:要分配的内存大小(字节)
- //返回值:新分配到的内存首地址.
- void *myrealloc(void *ptr,u32 size)
- {
- u32 offset;
- offset=mem_malloc(size);
- if(offset==0XFFFFFFFF)return NULL;
- else
- {
- mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size); //拷贝旧内存内容到新内存
- myfree(ptr); //释放旧内存
- return (void*)((u32)mallco_dev.membase+offset); //返回新内存首地址
- }
- }
复制代码malloc.h内容如下: - #ifndef __MALLOC_H
- #define __MALLOC_H
- #include "stm32f10x.h"
- #ifndef NULL
- #define NULL 0
- #endif
- #define MEM_BLOCK_SIZE 32 //内存块大小为32字节
- #define MEM_MAX_SIZE 16*1024 //最大管理内存 2K
- #define MEM_ALLOC_TABLE_SIZE MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
- //内存管理控制器
- struct _m_mallco_dev
- {
- void (*init)(void); //初始化
- u8 (*perused)(void); //内存使用率
- u8 *membase; //内存池
- u16 *memmap; //内存管理状态表
- u8 memrdy; //内存管理是否就绪
- };
- extern struct _m_mallco_dev mallco_dev; //在mallco.c里面定义
- void mymemset(void *s,u8 c,u32 count); //设置内存
- void mymemcpy(void *des,void *src,u32 n);//复制内存
- void mem_init(void); //内存管理初始化函数
- u32 mem_malloc(u32 size); //内存分配
- u8 mem_free(u32 offset); //内存释放
- u8 mem_perused(void); //获得内存使用率
- ////////////////////////////////////////////////////////////////////////////////
- //用户调用函数
- void myfree(void *ptr); //内存释放
- void *mymalloc(u32 size); //内存分配
- void *myrealloc(void *ptr,u32 size);//重新分配内存
- #endif
复制代码cJSON.c的内容也全在下面 - 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 #include <string.h>
- 27 #include <stdio.h>
- 28 #include <math.h>
- 29 #include <stdlib.h>
- 30 #include <float.h>
- 31 #include <limits.h>
- 32 #include <ctype.h>
- 33 #include "cJSON.h"
- 34
- 35 #include "malloc.h"
- 36
- 37 static const char *ep;
- 38
- 39 const char *cJSON_GetErrorPtr(void) {return ep;}
- 40
- 41 static int cJSON_strcasecmp(const char *s1,const char *s2)
- 42 {
- 43 if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
- 44 for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
- 45 return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
- 46 }
- 47
- 48 static void *(*cJSON_malloc)(size_t sz) = mymalloc;
- 49 static void (*cJSON_free)(void *ptr) = myfree;
- 50
- 51 static char* cJSON_strdup(const char* str)
- 52 {
- 53 size_t len;
- 54 char* copy;
- 55
- 56 len = strlen(str) + 1;
- 57 if (!(copy = (char*)cJSON_malloc(len))) return 0;
- 58 memcpy(copy,str,len);
- 59 return copy;
- 60 }
- 61
- 62 void cJSON_InitHooks(cJSON_Hooks* hooks)
- 63 {
- 64 if (!hooks) { /* Reset hooks */
- 65 cJSON_malloc = malloc;
- 66 cJSON_free = free;
- 67 return;
- 68 }
- 69
- 70 cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
- 71 cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
- 72 }
- 73
- 74 /* Internal constructor. */
- 75 static cJSON *cJSON_New_Item(void)
- 76 {
- 77 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
- 78 if (node) memset(node,0,sizeof(cJSON));
- 79 return node;
- 80 }
- 81
- 82 /* Delete a cJSON structure. */
- 83 void cJSON_Delete(cJSON *c)
- 84 {
- 85 cJSON *next;
- 86 while (c)
- 87 {
- 88 next=c->next;
- 89 if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
- 90 if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
- 91 if (c->string) cJSON_free(c->string);
- 92 cJSON_free(c);
- 93 c=next;
- 94 }
- 95 }
- 96
- 97 /* Parse the input text to generate a number, and populate the result into item. */
- 98 static const char *parse_number(cJSON *item,const char *num)
- 99 {
- 100 double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
- 101
- 102 if (*num=='-') sign=-1,num++; /* Has sign? */
- 103 if (*num=='0') num++; /* is zero */
- 104 if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
- 105 if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
- 106 if (*num=='e' || *num=='E') /* Exponent? */
- 107 { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
- 108 while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
- 109 }
- 110
- 111 n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
- 112
- 113 item->valuedouble=n;
- 114 item->valueint=(int)n;
- 115 item->type=cJSON_Number;
- 116 return num;
- 117 }
- 118
- 119 /* Render the number nicely from the given item into a string. */
- 120 static char *print_number(cJSON *item)
- 121 {
- 122 char *str;
- 123 double d=item->valuedouble;
- 124 if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
- 125 {
- 126 str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
- 127 if (str) sprintf(str,"%d",item->valueint);
- 128 }
- 129 else
- 130 {
- 131 str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
- 132 if (str)
- 133 {
- 134 if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
- 135 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
- 136 else sprintf(str,"%f",d);
- 137 }
- 138 }
- 139 return str;
- 140 }
- 141
- 142 static unsigned parse_hex4(const char *str)
- 143 {
- 144 unsigned h=0;
- 145 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
- 146 h=h<<4;str++;
- 147 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
- 148 h=h<<4;str++;
- 149 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
- 150 h=h<<4;str++;
- 151 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
- 152 return h;
- 153 }
- 154
- 155 /* Parse the input text into an unescaped cstring, and populate item. */
- 156 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- 157 static const char *parse_string(cJSON *item,const char *str)
- 158 {
- 159 const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
- 160 if (*str!='"') {ep=str;return 0;} /* not a string! */
- 161
- 162 while (*ptr!='"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
- 163
- 164 out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
- 165 if (!out) return 0;
- 166
- 167 ptr=str+1;ptr2=out;
- 168 while (*ptr!='"' && *ptr)
- 169 {
- 170 if (*ptr!='\\') *ptr2++=*ptr++;
- 171 else
- 172 {
- 173 ptr++;
- 174 switch (*ptr)
- 175 {
- 176 case 'b': *ptr2++='\b'; break;
- 177 case 'f': *ptr2++='\f'; break;
- 178 case 'n': *ptr2++='\n'; break;
- 179 case 'r': *ptr2++='\r'; break;
- 180 case 't': *ptr2++='\t'; break;
- 181 case 'u': /* transcode utf16 to utf8. */
- 182 uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
- 183
- 184 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
- 185
- 186 if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
- 187 {
- 188 if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
- 189 uc2=parse_hex4(ptr+3);ptr+=6;
- 190 if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
- 191 uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
- 192 }
- 193
- 194 len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
- 195
- 196 switch (len) {
- 197 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
- 198 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
- 199 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
- 200 case 1: *--ptr2 =(uc | firstByteMark[len]);
- 201 }
- 202 ptr2+=len;
- 203 break;
- 204 default: *ptr2++=*ptr; break;
- 205 }
- 206 ptr++;
- 207 }
- 208 }
- 209 *ptr2=0;
- 210 if (*ptr=='"') ptr++;
- 211 item->valuestring=out;
- 212 item->type=cJSON_String;
- 213 return ptr;
- 214 }
- 215
- 216 /* Render the cstring provided to an escaped version that can be printed. */
- 217 static char *print_string_ptr(const char *str)
- 218 {
- 219 const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
- 220
- 221 if (!str) return cJSON_strdup("");
- 222 ptr=str;while ((token=*ptr) && ++len) {if (strchr(""\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
- 223
- 224 out=(char*)cJSON_malloc(len+3);
- 225 if (!out) return 0;
- 226
- 227 ptr2=out;ptr=str;
- 228 *ptr2++='"';
- 229 while (*ptr)
- 230 {
- 231 if ((unsigned char)*ptr>31 && *ptr!='"' && *ptr!='\\') *ptr2++=*ptr++;
- 232 else
- 233 {
- 234 *ptr2++='\\';
- 235 switch (token=*ptr++)
- 236 {
- 237 case '\\': *ptr2++='\\'; break;
- 238 case '"': *ptr2++='"'; break;
- 239 case '\b': *ptr2++='b'; break;
- 240 case '\f': *ptr2++='f'; break;
- 241 case '\n': *ptr2++='n'; break;
- 242 case '\r': *ptr2++='r'; break;
- 243 case '\t': *ptr2++='t'; break;
- 244 default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
- 245 }
- 246 }
- 247 }
- 248 *ptr2++='"';*ptr2++=0;
- 249 return out;
- 250 }
- 251 /* Invote print_string_ptr (which is useful) on an item. */
- 252 static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
- 253
- 254 /* Predeclare these prototypes. */
- 255 static const char *parse_value(cJSON *item,const char *value);
- 256 static char *print_value(cJSON *item,int depth,int fmt);
- 257 static const char *parse_array(cJSON *item,const char *value);
- 258 static char *print_array(cJSON *item,int depth,int fmt);
- 259 static const char *parse_object(cJSON *item,const char *value);
- 260 static char *print_object(cJSON *item,int depth,int fmt);
- 261
- 262 /* Utility to jump whitespace and cr/lf */
- 263 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
- 264
- 265 /* Parse an object - create a new root, and populate. */
- 266 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
- 267 {
- 268 const char *end=0;
- 269 cJSON *c=cJSON_New_Item();
- 270 ep=0;
- 271 if (!c) return 0; /* memory fail */
- 272
- 273 end=parse_value(c,skip(value));
- 274 if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
- 275
- 276 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
- 277 if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
- 278 if (return_parse_end) *return_parse_end=end;
- 279 return c;
- 280 }
- 281 /* Default options for cJSON_Parse */
- 282 cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
- 283
- 284 /* Render a cJSON item/entity/structure to text. */
- 285 char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
- 286 char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
- 287
- 288 /* Parser core - when encountering text, process appropriately. */
- 289 static const char *parse_value(cJSON *item,const char *value)
- 290 {
- 291 if (!value) return 0; /* Fail on null. */
- 292 if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
- 293 if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
- 294 if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
- 295 if (*value=='"') { return parse_string(item,value); }
- 296 if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
- 297 if (*value=='[') { return parse_array(item,value); }
- 298 if (*value=='{') { return parse_object(item,value); }
- 299
- 300 ep=value;return 0; /* failure. */
- 301 }
- 302
- 303 /* Render a value to text. */
- 304 static char *print_value(cJSON *item,int depth,int fmt)
- 305 {
- 306 char *out=0;
- 307 if (!item) return 0;
- 308 switch ((item->type)&255)
- 309 {
- 310 case cJSON_NULL: out=cJSON_strdup("null"); break;
- 311 case cJSON_False: out=cJSON_strdup("false");break;
- 312 case cJSON_True: out=cJSON_strdup("true"); break;
- 313 case cJSON_Number: out=print_number(item);break;
- 314 case cJSON_String: out=print_string(item);break;
- 315 case cJSON_Array: out=print_array(item,depth,fmt);break;
- 316 case cJSON_Object: out=print_object(item,depth,fmt);break;
- 317 }
- 318 return out;
- 319 }
- 320
- 321 /* Build an array from input text. */
- 322 static const char *parse_array(cJSON *item,const char *value)
- 323 {
- 324 cJSON *child;
- 325 if (*value!='[') {ep=value;return 0;} /* not an array! */
- 326
- 327 item->type=cJSON_Array;
- 328 value=skip(value+1);
- 329 if (*value==']') return value+1; /* empty array. */
- 330
- 331 item->child=child=cJSON_New_Item();
- 332 if (!item->child) return 0; /* memory fail */
- 333 value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
- 334 if (!value) return 0;
- 335
- 336 while (*value==',')
- 337 {
- 338 cJSON *new_item;
- 339 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
- 340 child->next=new_item;new_item->prev=child;child=new_item;
- 341 value=skip(parse_value(child,skip(value+1)));
- 342 if (!value) return 0; /* memory fail */
- 343 }
- 344
- 345 if (*value==']') return value+1; /* end of array */
- 346 ep=value;return 0; /* malformed. */
- 347 }
- 348
- 349 /* Render an array to text */
- 350 static char *print_array(cJSON *item,int depth,int fmt)
- 351 {
- 352 char **entries;
- 353 char *out=0,*ptr,*ret;int len=5;
- 354 cJSON *child=item->child;
- 355 int numentries=0,i=0,fail=0;
- 356
- 357 /* How many entries in the array? */
- 358 while (child) numentries++,child=child->next;
- 359 /* Explicitly handle numentries==0 */
- 360 if (!numentries)
- 361 {
- 362 out=(char*)cJSON_malloc(3);
- 363 if (out) strcpy(out,"[]");
- 364 return out;
- 365 }
- 366 /* Allocate an array to hold the values for each */
- 367 entries=(char**)cJSON_malloc(numentries*sizeof(char*));
- 368 if (!entries) return 0;
- 369 memset(entries,0,numentries*sizeof(char*));
- 370 /* Retrieve all the results: */
- 371 child=item->child;
- 372 while (child && !fail)
- 373 {
- 374 ret=print_value(child,depth+1,fmt);
- 375 entries[i++]=ret;
- 376 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
- 377 child=child->next;
- 378 }
- 379
- 380 /* If we didn't fail, try to malloc the output string */
- 381 if (!fail) out=(char*)cJSON_malloc(len);
- 382 /* If that fails, we fail. */
- 383 if (!out) fail=1;
- 384
- 385 /* Handle failure. */
- 386 if (fail)
- 387 {
- 388 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
- 389 cJSON_free(entries);
- 390 return 0;
- 391 }
- 392
- 393 /* Compose the output array. */
- 394 *out='[';
- 395 ptr=out+1;*ptr=0;
- 396 for (i=0;i<numentries;i++)
- 397 {
- 398 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
- 399 if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
- 400 cJSON_free(entries[i]);
- 401 }
- 402 cJSON_free(entries);
- 403 *ptr++=']';*ptr++=0;
- 404 return out;
- 405 }
- 406
- 407 /* Build an object from the text. */
- 408 static const char *parse_object(cJSON *item,const char *value)
- 409 {
- 410 cJSON *child;
- 411 if (*value!='{') {ep=value;return 0;} /* not an object! */
- 412
- 413 item->type=cJSON_Object;
- 414 value=skip(value+1);
- 415 if (*value=='}') return value+1; /* empty array. */
- 416
- 417 item->child=child=cJSON_New_Item();
- 418 if (!item->child) return 0;
- 419 value=skip(parse_string(child,skip(value)));
- 420 if (!value) return 0;
- 421 child->string=child->valuestring;child->valuestring=0;
- 422 if (*value!=':') {ep=value;return 0;} /* fail! */
- 423 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
- 424 if (!value) return 0;
- 425
- 426 while (*value==',')
- 427 {
- 428 cJSON *new_item;
- 429 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
- 430 child->next=new_item;new_item->prev=child;child=new_item;
- 431 value=skip(parse_string(child,skip(value+1)));
- 432 if (!value) return 0;
- 433 child->string=child->valuestring;child->valuestring=0;
- 434 if (*value!=':') {ep=value;return 0;} /* fail! */
- 435 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
- 436 if (!value) return 0;
- 437 }
- 438
- 439 if (*value=='}') return value+1; /* end of array */
- 440 ep=value;return 0; /* malformed. */
- 441 }
- 442
- 443 /* Render an object to text. */
- 444 static char *print_object(cJSON *item,int depth,int fmt)
- 445 {
- 446 char **entries=0,**names=0;
- 447 char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
- 448 cJSON *child=item->child;
- 449 int numentries=0,fail=0;
- 450 /* Count the number of entries. */
- 451 while (child) numentries++,child=child->next;
- 452 /* Explicitly handle empty object case */
- 453 if (!numentries)
- 454 {
- 455 out=(char*)cJSON_malloc(fmt?depth+4:3);
- 456 if (!out) return 0;
- 457 ptr=out;*ptr++='{';
- 458 if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
- 459 *ptr++='}';*ptr++=0;
- 460 return out;
- 461 }
- 462 /* Allocate space for the names and the objects */
- 463 entries=(char**)cJSON_malloc(numentries*sizeof(char*));
- 464 if (!entries) return 0;
- 465 names=(char**)cJSON_malloc(numentries*sizeof(char*));
- 466 if (!names) {cJSON_free(entries);return 0;}
- 467 memset(entries,0,sizeof(char*)*numentries);
- 468 memset(names,0,sizeof(char*)*numentries);
- 469
- 470 /* Collect all the results into our arrays: */
- 471 child=item->child;depth++;if (fmt) len+=depth;
- 472 while (child)
- 473 {
- 474 names[i]=str=print_string_ptr(child->string);
- 475 entries[i++]=ret=print_value(child,depth,fmt);
- 476 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
- 477 child=child->next;
- 478 }
- 479
- 480 /* Try to allocate the output string */
- 481 if (!fail) out=(char*)cJSON_malloc(len);
- 482 if (!out) fail=1;
- 483
- 484 /* Handle failure */
- 485 if (fail)
- 486 {
- 487 for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
- 488 cJSON_free(names);cJSON_free(entries);
- 489 return 0;
- 490 }
- 491
- 492 /* Compose the output: */
- 493 *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
- 494 for (i=0;i<numentries;i++)
- 495 {
- 496 if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
- 497 strcpy(ptr,names[i]);ptr+=strlen(names[i]);
- 498 *ptr++=':';if (fmt) *ptr++='\t';
- 499 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
- 500 if (i!=numentries-1) *ptr++=',';
- 501 if (fmt) *ptr++='\n';*ptr=0;
- 502 cJSON_free(names[i]);cJSON_free(entries[i]);
- 503 }
- 504
- 505 cJSON_free(names);cJSON_free(entries);
- 506 if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
- 507 *ptr++='}';*ptr++=0;
- 508 return out;
- 509 }
- 510
- 511 /* Get Array size/item / object item. */
- 512 int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
- 513 cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
- 514 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
- 515
- 516 /* Utility for array list handling. */
- 517 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
- 518 /* Utility for handling references. */
- 519 static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;mymemcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
- 520
- 521 /* Add item to array/object. */
- 522 void cJSON_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; suffix_object(c,item);}}
- 523 void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
- 524 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
- 525 void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
- 526
- 527 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
- 528 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;}
- 529 void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
- 530 cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
- 531 void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
- 532
- 533 /* Replace array/object items with new ones. */
- 534 void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
- 535 newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
- 536 if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
- 537 void cJSON_ReplaceItemInObject(cJSON *object,const char *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);}}
- 538
- 539 /* Create basic types: */
- 540 cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
- 541 cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
- 542 cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
- 543 cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
- 544 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;}
- 545 cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
- 546 cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
- 547 cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
- 548
- 549 /* Create Arrays: */
- 550 cJSON *cJSON_CreateIntArray(const int *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;}
- 551 cJSON *cJSON_CreateFloatArray(const float *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;}
- 552 cJSON *cJSON_CreateDoubleArray(const double *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;}
- 553 cJSON *cJSON_CreateStringArray(const char **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;}
- 554
- 555 /* Duplication */
- 556 cJSON *cJSON_Duplicate(cJSON *item,int recurse)
- 557 {
- 558 cJSON *newitem,*cptr,*nptr=0,*newchild;
- 559 /* Bail on bad ptr */
- 560 if (!item) return 0;
- 561 /* Create new item */
- 562 newitem=cJSON_New_Item();
- 563 if (!newitem) return 0;
- 564 /* Copy over all vars */
- 565 newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
- 566 if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
- 567 if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
- 568 /* If non-recursive, then we're done! */
- 569 if (!recurse) return newitem;
- 570 /* Walk the ->next chain for the child. */
- 571 cptr=item->child;
- 572 while (cptr)
- 573 {
- 574 newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
- 575 if (!newchild) {cJSON_Delete(newitem);return 0;}
- 576 if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
- 577 else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
- 578 cptr=cptr->next;
- 579 }
- 580 return newitem;
- 581 }
- 582
- 583 void cJSON_Minify(char *json)
- 584 {
- 585 char *into=json;
- 586 while (*json)
- 587 {
- 588 if (*json==' ') json++;
- 589 else if (*json=='\t') json++; // Whitespace characters.
- 590 else if (*json=='\r') json++;
- 591 else if (*json=='\n') json++;
- 592 else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
- 593 else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
- 594 else if (*json=='"'){*into++=*json++;while (*json && *json!='"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are " sensitive.
- 595 else *into++=*json++; // All other characters.
- 596 }
- 597 *into=0; // and null-terminate.
- 598 }cJSON.h内容如下
- 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 #ifndef cJSON__h
- 24 #define cJSON__h
- 25
- 26 #include <stddef.h>
- 27
- 28 #ifdef __cplusplus
- 29 extern "C"
- 30 {
- 31 #endif
- 32
- 33 /* cJSON Types: */
- 34 #define cJSON_False 0
- 35 #define cJSON_True 1
- 36 #define cJSON_NULL 2
- 37 #define cJSON_Number 3
- 38 #define cJSON_String 4
- 39 #define cJSON_Array 5
- 40 #define cJSON_Object 6
- 41
- 42 #define cJSON_IsReference 256
- 43
- 44 /* The cJSON structure: */
- 45 typedef struct cJSON {
- 46 struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
- 47 struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
- 48
- 49 int type; /* The type of the item, as above. */
- 50
- 51 char *valuestring; /* The item's string, if type==cJSON_String */
- 52 int valueint; /* The item's number, if type==cJSON_Number */
- 53 double valuedouble; /* The item's number, if type==cJSON_Number */
- 54
- 55 char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
- 56 } cJSON;
- 57
- 58
- 59
- 60 typedef struct cJSON_Hooks {
- 61 void *(*malloc_fn)(size_t sz);
- 62 void (*free_fn)(void *ptr);
- 63 } cJSON_Hooks;
- 64
- 65 /* Supply malloc, realloc and free functions to cJSON */
- 66 extern void cJSON_InitHooks(cJSON_Hooks* hooks);
- 67
- 68
- 69 /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
- 70 extern cJSON *cJSON_Parse(const char *value);
- 71 /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
- 72 extern char *cJSON_Print(cJSON *item);
- 73 /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
- 74 extern char *cJSON_PrintUnformatted(cJSON *item);
- 75 /* Delete a cJSON entity and all subentities. */
- 76 extern void cJSON_Delete(cJSON *c);
- 77
- 78 /* Returns the number of items in an array (or object). */
- 79 extern int cJSON_GetArraySize(cJSON *array);
- 80 /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
- 81 extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
- 82 /* Get item "string" from object. Case insensitive. */
- 83 extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
- 84
- 85 /* 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. */
- 86 extern const char *cJSON_GetErrorPtr(void);
- 87
- 88 /* These calls create a cJSON item of the appropriate type. */
- 89 extern cJSON *cJSON_CreateNull(void);
- 90 extern cJSON *cJSON_CreateTrue(void);
- 91 extern cJSON *cJSON_CreateFalse(void);
- 92 extern cJSON *cJSON_CreateBool(int b);
- 93 extern cJSON *cJSON_CreateNumber(double num);
- 94 extern cJSON *cJSON_CreateString(const char *string);
- 95 extern cJSON *cJSON_CreateArray(void);
- 96 extern cJSON *cJSON_CreateObject(void);
- 97
- 98 /* These utilities create an Array of count items. */
- 99 extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
- 100 extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
- 101 extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
- 102 extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
- 103
- 104 /* Append item to the specified array/object. */
- 105 extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
- 106 extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
- 107 /* 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. */
- 108 extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
- 109 extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
- 110
- 111 /* Remove/Detatch items from Arrays/Objects. */
- 112 extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
- 113 extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
- 114 extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
- 115 extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
- 116
- 117 /* Update array items. */
- 118 extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
- 119 extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
- 120
- 121 /* Duplicate a cJSON item */
- 122 extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
- 123 /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
- 124 need to be released. With recurse!=0, it will duplicate any children connected to the item.
- 125 The item->next and ->prev pointers are always zero on return from Duplicate. */
- 126
- 127 /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
- 128 extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
- 129
- 130 extern void cJSON_Minify(char *json);
- 131
- 132 /* Macros for creating things quickly. */
- 133 #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
- 134 #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
- 135 #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
- 136 #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
- 137 #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
- 138 #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
- 139
- 140 /* When assigning an integer value, it needs to be propagated to valuedouble too. */
- 141 #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
- 142
- 143 #ifdef __cplusplus
- 144 }
- 145 #endif
- 146
- 147 #endif
复制代码- /*
- Copyright (c) 2009 Dave Gamble
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #ifndef cJSON__h
- #define cJSON__h
- #include <stddef.h>
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- /* cJSON Types: */
- #define cJSON_False 0
- #define cJSON_True 1
- #define cJSON_NULL 2
- #define cJSON_Number 3
- #define cJSON_String 4
- #define cJSON_Array 5
- #define cJSON_Object 6
- #define cJSON_IsReference 256
- /* The cJSON structure: */
- typedef struct cJSON {
- struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
- struct cJSON *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 */
- 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;
- typedef struct cJSON_Hooks {
- void *(*malloc_fn)(size_t sz);
- void (*free_fn)(void *ptr);
- } cJSON_Hooks;
- /* Supply malloc, realloc and free functions to cJSON */
- extern void cJSON_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(const char *value);
- /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
- extern char *cJSON_Print(cJSON *item);
- /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
- extern char *cJSON_PrintUnformatted(cJSON *item);
- /* Delete a cJSON entity and all subentities. */
- extern void cJSON_Delete(cJSON *c);
- /* Returns the number of items in an array (or object). */
- extern int cJSON_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,const char *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. */
- extern const char *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_CreateString(const char *string);
- extern cJSON *cJSON_CreateArray(void);
- extern cJSON *cJSON_CreateObject(void);
- /* These utilities create an Array of count items. */
- extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
- extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
- extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
- extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
- /* Append item to the specified array/object. */
- extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
- extern void cJSON_AddItemToObject(cJSON *object,const char *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. */
- extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
- extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
- /* Remove/Detatch items from Arrays/Objects. */
- extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
- extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
- extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
- extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
- /* Update array items. */
- extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
- extern void cJSON_ReplaceItemInObject(cJSON *object,const char *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(const char *value,const char **return_parse_end,int require_null_terminated);
- extern void cJSON_Minify(char *json);
- /* Macros for creating things quickly. */
- #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
- #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
- #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
- #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
- #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
- #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
- /* When assigning an integer value, it needs to be propagated to valuedouble too. */
- #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
- #ifdef __cplusplus
- }
- #endif
- #endif
复制代码下面是JSON数据的解析部分,简单说来就是对号入座。 - /**************************************************************************
- 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令
- 入口参数:JSON格式的字符串,
- 返回 值:指令类型
- 注 意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数
- **************************************************************************/
- CommandType GetCommandFromServer(char * JsonDataFromSocket)
- {
- // ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替
- // Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替
- CommandType cmdtype;
- RobotJSON_CMD_TypeDef json_cmd;
- HelloJSON_Ack_TypeDef json_ack;
- cJSON *root,*command_root;
- root = cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)
- if(!root)
- {
- //printf("get cJSON faild !\n");
- cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对
- if(!command_root)
- {
- //printf("No RobotCommand !\n");
- command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对
- if(!command_root)
- {
- //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回0
- cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else{
- json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
- if(!json_ack.ID)
- {
- cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);
- }
- json_ack.Time = cJSON_GetObjectItem(command_root,"Time");
- if(!json_ack.Time)
- {
- cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);
- }
- cmdtype=HELLO_ACK;//如果没有,就直接返回0
- }
- }
- else
- {
- //运动命令
- json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");
- if(!json_cmd.Command)
- {
- //printf("no Command!\n");
- //cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("Command is %s\r\n", robocmd.Command->valuestring);
- strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);
- //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议
- }
- //速度指令
- json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");
- if(!json_cmd.Speed)
- {
- //printf("no Speed!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("Speed is %d\r\n", json_cmd.Speed->valueint);
- Cmd_From_Server.Speed=json_cmd.Speed->valueint;
- }
- //运行次数
- json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");
- if(!json_cmd.RunCount)
- {
- //printf("no RunCount!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);
- Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;
- }
- //开始位置
- json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");
- if(!json_cmd.StartPosition)
- {
- //printf("no StartPosition!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);
- Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
- }
- //结束位置
- json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");
- if(!json_cmd.EndPosition)
- {
- //printf("no EndPosition!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);
- Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
- }
- //目标位置TargetPosition
- json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");
- if(!json_cmd.TargetPosition)
- {
- //printf("no TargetPosition!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);
- Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
- }
- //*工作模式WorkMode;
- json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");
- if(!json_cmd.WorkMode)
- {
- //printf("no WorkMode!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);
- strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);
- }
- //step
- json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");
- if(!json_cmd.Step)
- {
- //printf("no Step!\n");
- // cmdtype=NOCOMMAND;//如果没有,就直接返回0
- }
- else
- {
- //printf("Step is %d\r\n",json_cmd.Step->valueint);
- Cmd_From_Server.Step=json_cmd.Step->valueint;
- }
- cmdtype= COMMAND;
- }
- }
- cJSON_Delete(root);
- return cmdtype;
- }
复制代码
|