你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32-cJSON库的打包和解析

[复制链接]
STMCU小助手 发布时间:2022-1-28 19:01
这几天使用了一下JSON在STM32103平台上的使用,还是很好用的,在此记录下。
JSON是啥我也不总结了,就是直观的看起来是一个有格式的字符串,看起来非常清楚明白,有点像Python中的dicitionary的意思,实际使用的过程中主要就是“打包”和“解析”。下面直接来代码。
  1. char * Status_to_cJSON( char * cJSONROOM, ROBOStatus_TypeDef status)//传入一个变量的指针,这里cJSONROOM是一个全局变量(一个提前规定大小的字符数组),用来存放转换之后的JSON字符串
    ) n8 }$ }; k: n& Y. G& x9 v

  2. % E/ ?' A0 y6 B2 e; |3 H
  3. {
    8 m. M0 g" e& C0 g0 o6 }$ a

  4. ( {, |/ u3 p3 C$ s1 n5 D
  5.       char *result;0 N# n$ h+ }% Q3 X$ \% s0 s& S

  6. # _/ F/ V! M: b. `
  7.       cJSON *root,*subroot;//新建两个cJSON的对象指针  j2 _1 R, F; l
  8. # N4 |+ s- I* k- I1 P" R
  9.       root=cJSON_CreateObject();//创建一个机器人状态的JSON对象
    ( U' B9 X$ x, q

  10. ( A3 T" q* t) t0 ^  Q
  11.       subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象
    , ^0 p  `8 X  z9 W3 E

  12. , W* G3 c2 O. r# G, o" i
  13.       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。
    0 X. U/ `6 j: T3 ], z
  14. - h' X" I6 ^( K
  15.       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);
    4 W% c6 j; `/ o

  16. * v) Q7 S! B  [% w1 q
  17. //同上% M# e: Q0 t/ {8 j7 W7 B( X! F

  18. 2 M! u3 K8 Y5 O/ J; o+ W
  19.   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);- `7 `. x& w! ?- P, H' r7 j& n

  20. - a- x- z* z( G
  21. //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型
    & N7 C6 ?) f# K# ^7 Q

  22. ' ]1 z- K; D: y* H8 }
  23.       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);8 r& }, d. O4 s. Y
  24. 1 X. d( |9 I/ I4 n
  25.       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);( k* P1 L3 e' a8 |. k: u4 l& J

  26. ! n* ]/ h. B6 b& K& Z# C5 z
  27.       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);4 W7 M+ Q% t3 V( b! D) p$ w

  28. 4 k$ ~/ g% Q; _# F9 i) X
  29.      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);
    " L0 [% W2 {! s$ w! J* R

  30. ' r  I0 ?5 |3 K. B
  31.       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);
    0 a: X2 x+ a# e5 x; k! F

  32.   W2 m$ I' {3 Z& b( ]6 @- @) f0 Z
  33.       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);( p. V3 {% ]. N0 _1 b1 j9 N
  34.   D; u; `" G; w4 b; J
  35. cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);' t5 r: j. t. w. F3 k

  36. . k1 o! l% N/ g/ \
  37. cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);6 b! s/ q$ d" m  f
  38.   ?* d5 p3 V' n7 c$ E
  39.    cJSON_AddItemToObject(root, "RobotStatus", subroot);
    " V$ B$ G$ K* t2 P! E* C: X

  40. " ?4 O3 I9 h$ [/ @& O
  41.       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间4 K% E+ {/ P, `1 [. A* T) `
  42. 9 ]8 {# H3 D7 L2 X/ f
  43.       strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量* G9 b; }4 o1 i, ?& r/ q) `
  44. 6 a; Y. O# n; I- w3 I
  45.       cJSON_Delete(root);//最后将root根节点删除! [1 S+ x4 I+ M- C2 @

  46.   ?5 r' U# k+ d7 t( w9 i/ Z: h
  47.       myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃
    : R! ?8 Z; |6 M. c4 D! m! b4 C: t
  48. ' H% p5 f4 Y6 k/ H
  49.       return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。7 p* R. p6 S3 S0 }4 D

  50. 0 W5 U9 t4 k# z) Q" X' l
  51. }
复制代码
注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。
  1. #include "malloc.h"
    % l- ~% `/ U! J- j5 ?1 G
  2. 1 d1 m- C6 O; v
  3. //内存池(4字节对齐)
    - V3 [4 `$ d6 `5 `& r9 _
  4. __align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池5 K2 ]# F* y2 h2 S' l1 h0 }
  5. //内存管理表
    , L$ i& F/ k- t5 m) ?) u
  6. u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP. G$ ]( `/ d5 ~
  7. //内存管理参数
    8 t( e( @8 X" @& `( f# c
  8. const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小8 w# @: ?& ^2 C( O1 a) E
  9. const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小3 A, ^* C$ T* K+ v/ y) A
  10. const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小
    ; a; i9 H4 i% k/ I0 Q* }
  11. + t$ N% D+ t% E+ J2 x

  12. . m* u5 }" t$ R8 O+ b* u
  13. //内存管理控制器
    4 k, h& ?3 d2 V% `- f4 v
  14. struct _m_mallco_dev mallco_dev=* d. o6 x5 N- @0 F2 [- N) u
  15. {
    & H9 v* W4 e, G2 ?
  16.     mem_init,                //内存初始化) j: x/ L3 Y2 m) i- p  K" ~! @
  17.     mem_perused,      //内存使用率+ l/ j- V2 A9 D
  18.     membase,            //内存池0 b+ W3 @* V0 R; [& l1 Y' P; I5 H
  19.     memmapbase,     //内存管理状态表
    ) a3 }* r8 d6 C& d' @+ z
  20.     0,                        //内存管理未就绪
    + }- S7 ~/ X2 \, T- T; n
  21. };
    $ l7 K2 i* T+ {- O% N8 \
  22. " k$ M4 e& t" ~& _, E6 ]; z5 v$ f
  23. //复制内存: h2 m6 s  r$ P: }, R* t7 w% ?+ Z% d
  24. //*des:目的地址
      d9 d( T  C) [; o4 t: x, i6 E: M
  25. //*src:源地址$ }: x( I0 W( q& m
  26. //n:需要复制的内存长度(字节为单位). V! ^8 S* f( v
  27. void mymemcpy(void *des,void *src,u32 n)# t5 Q8 _! [: t0 W0 P
  28. {
    + l/ @& |$ {1 c8 e6 V9 B' D
  29.   u8 *xdes=des;
    9 @  J  \6 v$ F* z
  30.     u8 *xsrc=src;, d' [  V+ _1 p' q8 k$ {- Z  p
  31.   while(n--)*xdes++=*xsrc++;4 e! q4 V8 }. e1 }6 q" n0 L: s
  32. }" Q3 N! q, r; ^& E2 I9 k
  33. & \! R: H  {. C. j. B3 h2 r9 o
  34. //设置内存
    & J! `( L0 a  p' u
  35. //*s:内存首地址
    . l0 v3 I2 y5 @7 o
  36. //c :要设置的值2 e$ {' w9 T3 U
  37. //count:需要设置的内存大小(字节为单位)
    ( A2 D* }7 @# I* G2 W' }1 x
  38. void mymemset(void *s,u8 c,u32 count)
    0 `  Q" C4 \1 I  |) J
  39. {9 m& e5 m% e9 S
  40.     u8 *xs = s;
    $ \2 O; T- O, n  b
  41.     while(count--)*xs++=c;
    * }9 c# a$ X, o: \) z% a) e
  42. }5 l& j) ]& k" Q. j1 d5 `9 L3 u
  43. 2 x$ ^: a% O7 z- Y; Z
  44. //内存管理初始化8 _# f. [3 i7 v/ B( I
  45. //memx:所属内存块1 B; k$ i1 P  s! T3 X+ K
  46. void mem_init(void)
    " A8 E! ]% q) m+ x$ I3 e
  47. {
    ) n% k( ?6 a7 @( J3 G
  48.   mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零/ f+ U0 R; a3 Q" ~3 j8 E
  49.     mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零* C7 D# X* Z( l
  50.     mallco_dev.memrdy=1;                                //内存管理初始化OK8 u$ r# J2 y6 W$ ]- C- m
  51. }
    8 Q2 h8 J9 A% \: C' @! B8 F

  52. 2 F* K% b6 E, o5 e
  53. //获取内存使用率
    ' a$ J' w  r4 Z- p% Q0 v9 {3 d
  54. //memx:所属内存块7 N/ ~4 B9 x2 W) F4 f
  55. //返回值:使用率(0~100)  z1 \! Y5 a" ]+ s
  56. u8 mem_perused(void)2 D' d; a* y1 S
  57. {
    5 `/ F* Z" Z# C3 K; t3 D
  58.     u32 used=0;
      ^' j  C1 }9 O3 c0 C" N* I+ k
  59.     u32 i;5 w: L9 ?' X, R, t
  60.     for(i=0;i<memtblsize;i++)
    + T9 M9 ]! Q7 n, z7 ]0 `
  61.     {4 w, I) m$ M# n3 F+ L* U& ]
  62.         if(mallco_dev.memmap[i])used++;
    # N/ |! H, H$ z( ?' H! J! \9 h
  63.     }4 B6 [& N' q$ ]" I
  64.     return (used*100)/(memtblsize);# Q9 m8 q: m$ h9 b
  65. }
    6 f1 u( J0 F. y3 o
  66. 6 X( p# S8 {7 W8 G' [6 C
  67. //内存分配(内部调用)
    3 r- }4 v: K" b3 z5 i
  68. //memx:所属内存块
    2 W+ y  L; a. C6 H
  69. //size:要分配的内存大小(字节)% R. W; H$ w- W$ Z
  70. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
    4 {" ], l) `9 J- i
  71. u32 mem_malloc(u32 size)7 d% E( s. P; g. \6 T
  72. {" ^9 x7 Y- B. y) K* W1 I
  73.     signed long offset=0;
    0 K7 |; l/ n# w# _
  74.     u16 nmemb;    //需要的内存块数* t% q- t7 n# c' h  L8 o0 B
  75.     u16 cmemb=0;//连续空内存块数
    5 L4 v# [8 f3 M8 S$ z" Q- B
  76.     u32 i;. Z  n& q. M& f( W9 g9 O  f
  77.     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化4 t$ `! \) y4 k3 s. {4 G
  78.     if(size==0)return 0XFFFFFFFF;//不需要分配8 E7 ~8 ~) ]0 R# S- P
  79. + f0 C2 M+ H; Q+ H3 J# J6 Z  K
  80.     nmemb=size/memblksize;      //获取需要分配的连续内存块数
    8 z9 @/ X" b( T" T* |  A
  81.     if(size%memblksize)nmemb++;
    . L3 e& T5 v. D  A/ u4 I* {
  82.     for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区$ V8 @9 L* E5 V4 p
  83.     {
    ; G; ~; }8 ^9 r9 x
  84.         if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加
    : f# R9 m- l* U; v! C
  85.         else cmemb=0;                                //连续内存块清零  l) T' ~1 @) }3 s% N& J  D. I9 I3 N
  86.         if(cmemb==nmemb)                            //找到了连续nmemb个空内存块/ p  I( M+ v! `* G
  87.         {
    % V1 m! p. v8 s, U
  88.             for(i=0;i<nmemb;i++)                      //标注内存块非空' p8 e/ r/ b) M# R
  89.             {
    % f, f! R1 ?, u" J% y- a
  90.                 mallco_dev.memmap[offset+i]=nmemb;
    - K* R) J0 c* x/ q5 i6 k
  91.             }
    3 f5 S& S8 w+ E4 t' A6 S: ?& g
  92.             return (offset*memblksize);//返回偏移地址" h! a7 f) v: h% L
  93.         }4 b( L. p' h( C$ E
  94.     }( K3 U% m, H/ g* I
  95.     return 0XFFFFFFFF;//未找到符合分配条件的内存块
    + A( g$ c& G# I! l. r
  96. }
    9 h, B! l6 s. h& P) H

  97. . K. ~+ }7 L0 u7 j# ~$ K2 j
  98. //释放内存(内部调用)) o5 z  B0 b' Z
  99. //memx:所属内存块2 d8 A9 Y, {" g
  100. //offset:内存地址偏移( x7 Z- e' ]6 @0 ?/ q/ z; n
  101. //返回值:0,释放成功;1,释放失败;- ?8 w" T! O* W
  102. u8 mem_free(u32 offset)
    % y4 o% \# A' s' K, `( m# ]
  103. {1 Q7 `8 B9 N  Q: Z- s; a, D
  104.     int i;
    : ?4 A3 ]! P  U9 E% k" P
  105.     if(!mallco_dev.memrdy)//未初始化,先执行初始化, P$ x; T5 S4 H: Z6 S8 a% K; [: u
  106.     {
    # Z. T9 p6 k8 n' `1 s: V3 _( j
  107.         mallco_dev.init();# Y4 c- Z7 @$ i
  108.         return 1;//未初始化
    . n  l/ q, J/ h' d
  109.     }
    8 E7 c% K  ^1 L9 M) Z
  110.     if(offset<memsize)//偏移在内存池内.4 Z  O5 n( w  K3 k4 k! X
  111.     {; Q' J" n2 d1 J9 |! Z# L$ O
  112.         int index=offset/memblksize;            //偏移所在内存块号码
    6 Z( k+ i- N; f& m. x3 n& ~$ F
  113.         int nmemb=mallco_dev.memmap[index];    //内存块数量
    ; [  }+ r( d; w* k% Z. l
  114.         for(i=0;i<nmemb;i++)                          //内存块清零
    5 @( Q4 i6 t6 H6 C, R
  115.         {
    ( Y# {8 y9 s' @/ Z
  116.             mallco_dev.memmap[index+i]=0;  ?5 j- x* M4 L: V
  117.         }
    + V7 _7 Q( F  z$ ?7 r) P2 k
  118.         return 0;
    6 a6 a" x) h' C7 R9 Q
  119.     }else return 2;//偏移超区了.* S- x1 X" U! V) O, N  r0 I
  120. }
    ( e- E' q; v2 q% \% b; L

  121. " b9 U0 m( [  y0 T& Q" N
  122. //释放内存(外部调用)# f1 H, j* P2 j/ W
  123. //memx:所属内存块
    ! g6 [6 E/ f% F% g
  124. //ptr:内存首地址
    7 w7 ~' D5 J, Q
  125. void myfree(void *ptr)
    2 U1 a" d! ^4 N7 ]7 S4 d
  126. {+ N8 B: e% K8 _1 x3 k/ g, E; ?1 E
  127.     u32 offset;
    . a5 y! k3 c3 ]. u
  128.     if(ptr==NULL)return;//地址为0.
    & \6 O) k; H; [. J$ `" w- g
  129.      offset=(u32)ptr-(u32)mallco_dev.membase;* P6 V6 V+ s/ d; z9 d; q2 e6 L) X
  130.     mem_free(offset);//释放内存
    - |$ b9 Y( Z+ v8 U. Z! z
  131. }
    , M' w% q, ?: v

  132. 0 l. S9 W- b0 t: Z0 _& v1 @9 J, D
  133. //分配内存(外部调用)
    4 x/ n$ `8 d( q4 n3 n. I, Z8 f
  134. //memx:所属内存块
    / z. H# J- A2 @& k3 j- T7 W
  135. //size:内存大小(字节)6 e3 B2 M: c  l% z
  136. //返回值:分配到的内存首地址.
    & D+ ]/ }9 A  d' \8 _
  137. void *mymalloc(u32 size)
    ' h; S4 [2 i& K6 V
  138. {
    , G1 i, z7 i3 p& l: p( K9 h
  139.     u32 offset;
    " F7 K% v) p4 S) [$ q# }5 q
  140.     offset=mem_malloc(size);
    ( [' {) o7 A# I2 f8 V& a; I# M- |
  141.     if(offset==0XFFFFFFFF)return NULL;1 ^% D1 c/ d( Q6 w3 Z& X  y& `
  142.     else return (void*)((u32)mallco_dev.membase+offset);
    + {* N. s7 p4 D/ _
  143. }9 V3 l) |7 D  A
  144. ( U) {/ m0 }6 J7 q$ k  K2 h
  145. //重新分配内存(外部调用)
    ' r7 e/ w1 z! X& ~9 {9 L
  146. //memx:所属内存块( [8 h, z, ]$ }1 t
  147. //*ptr:旧内存首地址
    6 _. `9 C" p2 k: o6 L
  148. //size:要分配的内存大小(字节)
    5 p! P9 O4 l' ~3 y, f$ s/ r
  149. //返回值:新分配到的内存首地址.
    * q) V$ X4 ~, O. ~0 o; c
  150. void *myrealloc(void *ptr,u32 size)& Z0 X( c: j: r- _# |
  151. {- B0 Y$ `- ]3 `
  152.     u32 offset;
    / U) s  F  B$ t* c5 z0 N
  153.     offset=mem_malloc(size);
    0 f; M, ^% x& l' T1 [1 K
  154.     if(offset==0XFFFFFFFF)return NULL;7 Q1 j3 n' X, s
  155.     else
    + U0 c& u7 l. |& \
  156.     {
    , @1 Z0 T0 I1 a- }( K$ I  r
  157.         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存3 i$ I3 u' H/ u" W
  158.         myfree(ptr);                                                        //释放旧内存* K/ `# E/ a  ^. h
  159.         return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址' V" v; \9 w5 X) Q
  160.     }$ T/ l8 B" I( p% j6 U. d
  161. }
复制代码
malloc.h内容如下:
  1. #ifndef __MALLOC_H) }3 ?# ^" S8 ?3 {
  2. #define __MALLOC_H5 G% T5 y2 @- f" s
  3. #include "stm32f10x.h"9 Y# o: b; D4 m0 `

  4. $ v, F9 ?/ x! v) k! ?
  5. #ifndef NULL
    $ ?0 i! Y6 A" O7 P; |- a
  6. #define NULL 0
      x! d( v- T; K5 t: e  N
  7. #endif# |/ i$ L+ v% Q# d& G3 e
  8. ( B' L0 s1 z- L% ^8 W
  9. #define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节  Z3 j  h1 n0 V+ p; J
  10. #define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K  F0 `0 D6 L% }; `) x
  11. #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
    , {% K% Z- ~; C2 f
  12. 0 F3 }& B0 t: D
  13. //内存管理控制器  r' r; C4 x! S7 X% O' G
  14. struct _m_mallco_dev; N1 ~% e; F2 V4 V/ `
  15. {3 W- f/ W6 G& `7 Z4 \
  16.     void (*init)(void);                    //初始化7 j- J; v3 i5 e+ T: D: e* c1 R
  17.     u8   (*perused)(void);                      //内存使用率/ F% Z3 L9 `- a  Q  o- C  f
  18.     u8       *membase;                    //内存池3 B1 m6 X# q% n2 h& f
  19.     u16   *memmap;                     //内存管理状态表
      L1 A1 p5 U" M- V; i, |" L
  20.     u8     memrdy;                         //内存管理是否就绪  B: c: B6 I0 Y' M% M  E& F: p- l: p; t
  21. };4 n7 s9 [4 a# q4 g

  22.   y! g. w1 q! h% ~/ s/ I
  23. extern struct _m_mallco_dev mallco_dev;     //在mallco.c里面定义
    $ R( Z4 g7 D0 n& F
  24. 5 a7 x1 n/ O" x: ~, S: N" r5 m! \* t1 \
  25. void mymemset(void *s,u8 c,u32 count);     //设置内存) }$ v3 i' ]4 E) d3 G1 J2 g1 h/ G. Y, ]# c
  26. void mymemcpy(void *des,void *src,u32 n);//复制内存
    " I$ u' B3 F- J' V+ y, z; A

  27. % v7 o$ Q/ k6 ]+ M8 B' P
  28. void mem_init(void);                     //内存管理初始化函数- ]. @; y' L, E" G9 H, X5 u: c& X7 k
  29. u32 mem_malloc(u32 size);         //内存分配
    ! ?, x; H, c0 W: ~9 v
  30. u8 mem_free(u32 offset);         //内存释放
    6 S- d% _0 w2 x+ }! ]6 N' n" Y
  31. u8 mem_perused(void);                 //获得内存使用率4 y# c4 A" `1 X4 p. ~- x, p
  32. ////////////////////////////////////////////////////////////////////////////////3 e) ?; L# g: b# f* C0 z8 s" k' x
  33. //用户调用函数5 R, I8 @# o2 \* s) q# N5 }
  34. void myfree(void *ptr);              //内存释放9 y* R" H% H  v- g# V0 L0 l1 I1 E1 r
  35. void *mymalloc(u32 size);            //内存分配" P( ^* k2 N4 t
  36. void *myrealloc(void *ptr,u32 size);//重新分配内存
    0 F. J5 i/ o9 F2 c" L# I- I
  37. #endif
复制代码
cJSON.c的内容也全在下面
  1. 1 /*4 q0 y  C( d' `$ Q2 c
  2.   2   Copyright (c) 2009 Dave Gamble& T5 W6 `/ C0 V7 V6 c- r
  3.   3
    7 ^( |5 v' Q7 v
  4.   4   Permission is hereby granted, free of charge, to any person obtaining a copy$ S: S% Z7 S) _, h
  5.   5   of this software and associated documentation files (the "Software"), to deal6 ]; `$ F- C: T! |7 ~$ z
  6.   6   in the Software without restriction, including without limitation the rights0 K" V( h  `% B  O% q% b
  7.   7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell4 n5 \2 H# Z& a# Y4 h) Y$ @
  8.   8   copies of the Software, and to permit persons to whom the Software is- q6 O% n. z6 c" N
  9.   9   furnished to do so, subject to the following conditions:: K6 }6 \8 m2 g9 a& T
  10. 10
    7 Q$ I( F0 Y8 J7 w; Q- \
  11. 11   The above copyright notice and this permission notice shall be included in
    - V7 w7 C/ K0 R) |. F" G
  12. 12   all copies or substantial portions of the Software.& x. B/ E; [# n& D% F
  13. 13 3 B$ a7 W- Y1 u! S$ f
  14. 14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR' q# D9 Y8 I3 F# Y  H* R4 x
  15. 15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  U  N, H" ^1 r1 N' e# ]
  16. 16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    6 O# E* f, r" [! x5 ~
  17. 17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER) L) D2 Q1 b; i
  18. 18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      _, r2 P& |! J1 q' @2 f
  19. 19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN) ?& V7 P! W4 Q8 g- T/ B" K) G6 C
  20. 20   THE SOFTWARE.
      |7 v" @% I8 b/ Q) L* ?; w) {
  21. 21 */
    ) H; [0 B) J- g! m0 e
  22. 22 ( ]  E) O  |9 n, z# u: S
  23. 23 /* cJSON */
    ! Q3 w5 }0 F& Q1 \$ E
  24. 24 /* JSON parser in C. */
    : m) m+ x" \4 t) t- z
  25. 25 ) j7 w* i  [5 z7 O0 W
  26. 26 #include <string.h>% _+ x; [! X! |; g9 @  D2 b
  27. 27 #include <stdio.h>
    3 J5 a; P* O! A* `
  28. 28 #include <math.h>  I: h6 V1 H% f
  29. 29 #include <stdlib.h>
    ' ?# O! c! L6 f3 b/ M! W
  30. 30 #include <float.h>
    ' q6 l8 g: N" ~; ~: a
  31. 31 #include <limits.h>* O! j4 r9 U! M$ r* G
  32. 32 #include <ctype.h>. N; D& V+ e6 `- f7 X/ A
  33. 33 #include "cJSON.h"
    4 o4 k* Z' Q# ?* g& k
  34. 34
    1 M8 L" i) w" e1 [- v! v
  35. 35 #include "malloc.h"% \8 ]& `% S& p2 C9 V
  36. 36
    - g4 `& }% w* P- A
  37. 37 static const char *ep;" D, g! c9 Y1 ]
  38. 38
    ; c, x8 u6 \3 Y% {- G2 u
  39. 39 const char *cJSON_GetErrorPtr(void) {return ep;}' `% [! I0 B0 l4 ^+ t) V2 L/ N
  40. 40 ; w$ s+ _5 k. R
  41. 41 static int cJSON_strcasecmp(const char *s1,const char *s2)% ~3 _3 ]% j0 K( I
  42. 42 {3 I7 j5 S" ]' Z) Y6 Y0 M
  43. 43     if (!s1) return (s1==s2)?0:1;if (!s2) return 1;: Q' ]& s7 I# I# x3 _
  44. 44     for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)    if(*s1 == 0)    return 0;" M# R$ e8 e! O2 y# f
  45. 45     return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
    9 Y7 {) w. S6 G  N* F: l, {/ G
  46. 46 }: R) w+ H" h' n7 L: w9 x
  47. 47
    4 m: H# Y; d& ~& w* |! g
  48. 48 static void *(*cJSON_malloc)(size_t sz) = mymalloc;9 A' N2 `: i+ Q* J# h3 L2 w( D
  49. 49 static void (*cJSON_free)(void *ptr) = myfree;
    9 y( g  C6 q( @! c# Y# K4 T
  50. 50 ' U# [# P' c* c: l0 c. E# n! C) M
  51. 51 static char* cJSON_strdup(const char* str)4 s$ b5 p+ `, V( i
  52. 52 {, K5 O) K. L5 U5 {9 g( \
  53. 53       size_t len;
    ' g5 E( y8 o" S5 R/ `
  54. 54       char* copy;4 ~& E( E1 r$ L+ z- B* M' a: j# [
  55. 55 $ W/ B& L% M1 n9 R/ F/ I& R6 T
  56. 56       len = strlen(str) + 1;
    # Y- z' K8 u; [, @
  57. 57       if (!(copy = (char*)cJSON_malloc(len))) return 0;1 _9 W  Y1 |: ?) c
  58. 58       memcpy(copy,str,len);4 A8 \: B- H# V- c) K
  59. 59       return copy;
    4 L, r1 g6 O5 n) x! w  Z5 c
  60. 60 }
    ' p7 L' A# V$ f; h( ~, d# o
  61. 61 8 X2 ^. Z5 ?4 Z+ _7 D
  62. 62 void cJSON_InitHooks(cJSON_Hooks* hooks)+ k: F$ X9 ^, i
  63. 63 {
    0 s3 I, q5 y8 b* R$ ~
  64. 64     if (!hooks) { /* Reset hooks */
    ' _3 [2 ]* v9 F" s3 ^
  65. 65         cJSON_malloc = malloc;1 a" I3 U3 `: J9 u  t
  66. 66         cJSON_free = free;
    # k4 k. r8 B- `2 W4 S0 q! A
  67. 67         return;
    4 {" h: U3 g1 l! F
  68. 68     }
    . z9 y0 h, q7 n* d  C5 v/ {! u: I& n3 v
  69. 69 % W8 V. A, ?% H+ \
  70. 70     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;" \* I4 C, C. `8 a
  71. 71     cJSON_free     = (hooks->free_fn)?hooks->free_fn:free;
    / N, r6 e1 v1 D
  72. 72 }- @& B  U( `+ P  ~: P1 L
  73. 73 + c+ R" s. k/ T5 N& ]
  74. 74 /* Internal constructor. */
    4 {( h8 P1 ~( W( g1 b
  75. 75 static cJSON *cJSON_New_Item(void)6 _* Z; p8 T  Y5 L) X
  76. 76 {
    & l7 C* x' h3 l" V1 d' y8 W
  77. 77     cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));2 F% z* G; i8 F) \
  78. 78     if (node) memset(node,0,sizeof(cJSON));, V" H/ Q& a" F
  79. 79     return node;% t$ ?$ t) E9 V. w: E! ]0 u
  80. 80 }
    ' Z/ N5 I2 L! c
  81. 81
    8 B3 m& z& w. g9 x9 r+ }0 a  V
  82. 82 /* Delete a cJSON structure. */0 `# C+ h2 m8 s  B. b( h
  83. 83 void cJSON_Delete(cJSON *c)
    6 W1 n3 I1 t( h$ v4 k) ~
  84. 84 {
    6 s* a. o) q6 [4 P& _( X
  85. 85     cJSON *next;- P" r% q% h' t/ u1 t4 V) }
  86. 86     while (c)
    ) w7 n8 R6 W- u/ D
  87. 87     {$ R. L6 R3 r- s
  88. 88         next=c->next;2 b0 s, l$ r, l' Y5 w# v8 ]
  89. 89         if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
    & g  U: H& c' B$ ^
  90. 90         if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
    / I6 S* M* ]) ~- m
  91. 91         if (c->string) cJSON_free(c->string);2 S1 `6 Y( M5 l+ r9 J  }
  92. 92         cJSON_free(c);6 ]2 L& \1 ?7 e
  93. 93         c=next;
      r; n8 z( a$ U; p* Q
  94. 94     }
    + [7 a4 _" U; U3 h/ N9 ^5 Z5 c
  95. 95 }8 K7 b. w: U( E, `) p, M
  96. 96
    & C% y1 G0 M; ]( L. ?/ ]1 N, I+ O+ \
  97. 97 /* Parse the input text to generate a number, and populate the result into item. */
    9 h" a  K6 K8 n* b3 x
  98. 98 static const char *parse_number(cJSON *item,const char *num)
    ( o2 J# \$ _, k* [# W, J' Z
  99. 99 {# C+ ]7 H  E- f' M' O0 i% A' x
  100. 100     double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;% c3 Z3 e* d  v& B, E
  101. 101
    1 _( ~# S8 E, p( C
  102. 102     if (*num=='-') sign=-1,num++;    /* Has sign? */
    4 H8 `  a' R( a6 |5 m! e" T
  103. 103     if (*num=='0') num++;            /* is zero */
    ) K* W& F. _* C& A  x0 d( D( a
  104. 104     if (*num>='1' && *num<='9')    do    n=(n*10.0)+(*num++ -'0');    while (*num>='0' && *num<='9');    /* Number? */# \' ]6 `+ g$ T9 _9 r) K
  105. 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? */' R7 A. l) m' K+ k- o
  106. 106     if (*num=='e' || *num=='E')        /* Exponent? */  X# [* `6 O: z: U; P+ u
  107. 107     {    num++;if (*num=='+') num++;    else if (*num=='-') signsubscale=-1,num++;        /* With sign? */' O, D  ~) i/ L/ X0 K* R% n/ Z+ R
  108. 108         while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');    /* Number? */! L" U' B2 J3 H, i
  109. 109     }
    4 a; ]9 B( P4 L$ a, t" E
  110. 110 ( f3 n, L; h, ]8 F7 {/ t
  111. 111     n=sign*n*pow(10.0,(scale+subscale*signsubscale));    /* number = +/- number.fraction * 10^+/- exponent */' E2 h3 E6 n4 s2 @6 ?) Y( @
  112. 112     5 K% Z1 h/ e- O% C
  113. 113     item->valuedouble=n;
    ' w. j7 ]- b9 _; t. `, y3 }6 J2 g- ?
  114. 114     item->valueint=(int)n;
    % T5 e1 H" n" W* V6 Z
  115. 115     item->type=cJSON_Number;* S4 }4 Z+ \+ ~; _; @
  116. 116     return num;! f" \1 J4 V1 t. o  |6 q% i5 N
  117. 117 }1 X  c7 E; K  |4 s
  118. 118 ; z4 d- b' T* D+ M( G
  119. 119 /* Render the number nicely from the given item into a string. */
    # ^6 d6 d! S) ~9 D: K/ A
  120. 120 static char *print_number(cJSON *item)
      r5 ]& ]+ X) C: Q+ T
  121. 121 {. o7 m. r7 _9 T$ b
  122. 122     char *str;& L  g: x* a, P! f- Q5 c
  123. 123     double d=item->valuedouble;
    5 V) k0 a" o+ H9 q/ z# u
  124. 124     if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
    ' `& B2 V& K# x; g; L
  125. 125     {0 r5 f- L* q  U: S
  126. 126         str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
    9 ]- u7 y  j0 X" m" |: r
  127. 127         if (str) sprintf(str,"%d",item->valueint);# K6 H" u  @9 _$ B) v
  128. 128     }8 T2 k, x- \/ _6 Y9 Y
  129. 129     else
    ! a( Y1 `$ q' @! \+ \
  130. 130     {' i1 w; L% C8 k
  131. 131         str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
    2 ]( q) N; U' J2 w5 ^2 d
  132. 132         if (str)) V* [' N! q) ^; ?
  133. 133         {
    9 B4 \7 x: v# o
  134. 134             if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);5 x  F! C# s7 d9 v6 t, \  D: b
  135. 135             else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)            sprintf(str,"%e",d);+ F# _6 [' u7 f7 v- }1 m
  136. 136             else                                                sprintf(str,"%f",d);
    " v' G8 B0 }0 ~; Y' a+ b
  137. 137         }$ Y5 L. b6 B6 G/ F. \. \1 {  ^
  138. 138     }7 g) Q* v- i# Y1 U9 P) f) B* A
  139. 139     return str;+ F  Y7 B% Y3 t; e0 v" R. E. S2 T
  140. 140 }5 s/ h! p! I1 v
  141. 141 8 l& H( Y' r/ a( F) C. d" d9 P
  142. 142 static unsigned parse_hex4(const char *str)
    ' i: G) {2 f  X
  143. 143 {3 e6 D0 y6 l0 l: w
  144. 144     unsigned h=0;6 ?, `& i" `( f$ e; K. u0 |
  145. 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;
    $ Q5 a6 }4 D2 D' n* J  t0 C# c
  146. 146     h=h<<4;str++;
    $ C1 z5 a- K9 b6 ^6 ]7 r3 p& f8 E
  147. 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;; b) {% Y: q4 }0 k7 T( k
  148. 148     h=h<<4;str++;
    3 n* z4 ^5 `1 {$ E! [( v% E
  149. 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;0 U$ O. k0 `7 w* Y4 t
  150. 150     h=h<<4;str++;
      U- j# o0 |( {$ p: i
  151. 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;
    & }& J8 l# f; Q" c$ p8 H
  152. 152     return h;0 y( S9 d! H& n" a
  153. 153 }
    - F9 \, z; ~/ t
  154. 154
    0 q) ^) r8 ^& r( V# x- ^  u
  155. 155 /* Parse the input text into an unescaped cstring, and populate item. */- A  f. V) x/ W% d% j
  156. 156 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
    ; Y8 V3 S! P' ]) k
  157. 157 static const char *parse_string(cJSON *item,const char *str)
    % I' k% X: r1 b. s+ P
  158. 158 {3 I& I& v- T' ]9 E) t  v( m; O6 e
  159. 159     const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
    7 }+ `: T* p, m
  160. 160     if (*str!='"') {ep=str;return 0;}    /* not a string! */0 {9 a1 R' q, U$ G- G
  161. 161     
    8 R+ n, j. ?; b$ X& h3 K
  162. 162     while (*ptr!='"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;    /* Skip escaped quotes. */: {( E+ S7 i6 O
  163. 163     6 V2 s% P' S- w" V
  164. 164     out=(char*)cJSON_malloc(len+1);    /* This is how long we need for the string, roughly. */
    7 T8 F3 w, X9 y" V
  165. 165     if (!out) return 0;  d" ~6 E% @* v* ~0 }$ {$ y
  166. 166     
    " h! ?' ], {. H: o
  167. 167     ptr=str+1;ptr2=out;
    9 [" {# c3 r& [% ?" x$ t/ Q
  168. 168     while (*ptr!='"' && *ptr), A/ G! V( h5 q/ m- x* ~3 W
  169. 169     {
    2 `) `: H. O, J7 g0 u
  170. 170         if (*ptr!='\\') *ptr2++=*ptr++;
    $ `- n. A0 }$ r4 ?: d
  171. 171         else) Z4 l4 S* {2 |3 w" C9 ~
  172. 172         {" N+ Q; S6 A2 C" M  u  k
  173. 173             ptr++;
    % l9 h& C* E1 l
  174. 174             switch (*ptr)
    ' y& t* w) i% I4 r4 G
  175. 175             {
    1 l9 ?. R) T' \; q' ]' `
  176. 176                 case 'b': *ptr2++='\b';    break;8 \/ n' `3 g+ [7 S8 Q( w; }
  177. 177                 case 'f': *ptr2++='\f';    break;
    ; Q# W9 o: [/ @" N) ~
  178. 178                 case 'n': *ptr2++='\n';    break;
    9 y, i1 {0 V# e/ n' S1 J
  179. 179                 case 'r': *ptr2++='\r';    break;
    9 I7 I# o% n& ^6 j% Q
  180. 180                 case 't': *ptr2++='\t';    break;' u0 B1 ~- U0 O  S# b, N: |9 ^1 a
  181. 181                 case 'u':     /* transcode utf16 to utf8. */
    4 j# m( l& A. h
  182. 182                     uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */' p5 [" ?( \$ ~) Q+ O4 w' U  B
  183. 183 8 \% `0 ]: [; ]- A' M( S) x
  184. 184                     if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    break;    /* check for invalid.    */
    # C  U+ N* s# X
  185. 185 & K$ c; ]: y" d6 ]! @
  186. 186                     if (uc>=0xD800 && uc<=0xDBFF)    /* UTF16 surrogate pairs.    */
    6 t; X2 @2 z# |$ [+ B
  187. 187                     {
    * i9 g! e4 @: l5 V. ?
  188. 188                         if (ptr[1]!='\\' || ptr[2]!='u')    break;    /* missing second-half of surrogate.    */  Z) {- A- G5 w/ K( y- W5 b- p
  189. 189                         uc2=parse_hex4(ptr+3);ptr+=6;
    ' k. r0 O% \% y/ v
  190. 190                         if (uc2<0xDC00 || uc2>0xDFFF)        break;    /* invalid second-half of surrogate.    */4 l$ F/ E# n* ?3 w5 k
  191. 191                         uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));* `% x+ f" S5 p5 ^
  192. 192                     }
    ! H  h  r4 S' g$ {9 Y1 {
  193. 193 0 C! e: }+ d' |0 p
  194. 194                     len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
    ' {/ x+ K0 \3 b3 E- i& W
  195. 195                     ! p0 Q. ?- G  V: K& n
  196. 196                     switch (len) {6 _: W* I6 X; I7 i. N
  197. 197                         case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
    , C4 K3 i" T2 x& u
  198. 198                         case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
    6 u5 G6 b2 {7 R; E
  199. 199                         case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
    . e  {% z- M$ w
  200. 200                         case 1: *--ptr2 =(uc | firstByteMark[len]);
    % l( y* N/ Q0 a  P- g2 v
  201. 201                     }' F" n+ E4 V7 y- A4 p# X
  202. 202                     ptr2+=len;0 v9 l" C" u, Z, ~0 @0 K! D
  203. 203                     break;6 z9 N) q6 p6 c0 c, C4 o! B% ^
  204. 204                 default:  *ptr2++=*ptr; break;" L  w5 f3 K8 e; ~5 d" C) S
  205. 205             }
    ! v! j3 y1 S; m# `! V" T9 Q
  206. 206             ptr++;8 O# v% G, }5 M) M
  207. 207         }" X  _/ L4 @4 j* \1 C
  208. 208     }. V- D. r, ?' R- h) \1 @& ^. d
  209. 209     *ptr2=0;
    % a! p2 x; O+ R6 `8 |' Q
  210. 210     if (*ptr=='"') ptr++;
    4 o7 L) }, I- e6 |
  211. 211     item->valuestring=out;) H2 Z# N$ N3 ^* ], Q
  212. 212     item->type=cJSON_String;
    ' S3 Z5 q# q7 c! R  H
  213. 213     return ptr;! H( [+ k3 Y' G+ A, @& d  R$ [
  214. 214 }
    5 L/ b" O$ Y" Q9 }4 c
  215. 215 $ ~* o$ s) K6 d0 |/ D7 I
  216. 216 /* Render the cstring provided to an escaped version that can be printed. */" P7 f& J# S+ n7 [
  217. 217 static char *print_string_ptr(const char *str)
    5 Q7 Z5 J4 M0 ?, s+ R9 P0 P( V
  218. 218 {5 F( B( X7 b% X$ ~: Q+ ?* r3 L  f
  219. 219     const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
    8 W3 G- |9 X7 ?7 [/ c9 ]
  220. 220     / a7 M9 [' `- U$ q. W2 U
  221. 221     if (!str) return cJSON_strdup("");3 c! f; ?- B9 f
  222. 222     ptr=str;while ((token=*ptr) && ++len) {if (strchr(""\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
    $ q# h% w! w1 ~8 W5 d! G5 Z2 j! I
  223. 223     
    ; F2 J# A1 t2 \9 M% ^+ v" J
  224. 224     out=(char*)cJSON_malloc(len+3);( e4 C; D5 x: B
  225. 225     if (!out) return 0;
    2 g! s5 n- J+ \5 F
  226. 226
    . F; C) a: m( C  g9 l! }
  227. 227     ptr2=out;ptr=str;& E# w) q) _* ~
  228. 228     *ptr2++='"';, B4 w* c, D" F% l5 k# r" Y% l
  229. 229     while (*ptr)  ~% d( w1 p7 y# Z# i5 U- ]( X; R, n
  230. 230     {
    ' w- M3 I6 g% h8 |  `
  231. 231         if ((unsigned char)*ptr>31 && *ptr!='"' && *ptr!='\\') *ptr2++=*ptr++;
    4 p! g* m& J) C
  232. 232         else5 S8 U# ~. Y5 b: {6 u/ I
  233. 233         {( i0 M3 c1 `7 |% _5 l
  234. 234             *ptr2++='\\';& O6 J. @  U/ i. @
  235. 235             switch (token=*ptr++)
    3 i( v" G% u& M
  236. 236             {
    9 y5 x, Z3 P2 U
  237. 237                 case '\\':    *ptr2++='\\';    break;
    ' n) P9 t, A/ \" C3 N
  238. 238                 case '"':    *ptr2++='"';    break;
    ' q' R7 `8 C) F3 }
  239. 239                 case '\b':    *ptr2++='b';    break;0 t6 `1 K8 x( ^; A
  240. 240                 case '\f':    *ptr2++='f';    break;
    2 F2 C- ]2 D6 c# s5 Y" [5 g% R& Q+ ]) F
  241. 241                 case '\n':    *ptr2++='n';    break;
    # P  w% ~% w' x; W/ {7 J
  242. 242                 case '\r':    *ptr2++='r';    break;( _7 k, z6 S4 `6 m$ ^- ~
  243. 243                 case '\t':    *ptr2++='t';    break;% n6 ?4 x! L# m) q: V
  244. 244                 default: sprintf(ptr2,"u%04x",token);ptr2+=5;    break;    /* escape and print */! a( c  R! f/ |0 n0 \
  245. 245             }1 X* W% Q" E" I  t7 ]* T4 p
  246. 246         }
    $ U3 v$ u- [( j4 W" j: m
  247. 247     }' J1 n0 _: b! h0 M% v
  248. 248     *ptr2++='"';*ptr2++=0;4 p6 t0 z3 R( ]4 {6 p7 B3 ~1 U# n5 i, s
  249. 249     return out;4 n) o, r; |9 f0 A
  250. 250 }  k( E8 ]- V9 t& h) W9 N
  251. 251 /* Invote print_string_ptr (which is useful) on an item. */
    " ?: Q& u# z8 T8 v- r/ n
  252. 252 static char *print_string(cJSON *item)    {return print_string_ptr(item->valuestring);}+ |, S& \. f) }0 O; L) Y1 {
  253. 253
    0 }( {2 \  Y0 H+ g% L
  254. 254 /* Predeclare these prototypes. */& U. m# o& G: r3 k
  255. 255 static const char *parse_value(cJSON *item,const char *value);
    1 Z0 w$ v6 f  T( t3 J5 \+ ~
  256. 256 static char *print_value(cJSON *item,int depth,int fmt);+ G( k4 }" D* O4 m
  257. 257 static const char *parse_array(cJSON *item,const char *value);
    # S+ n8 U" m1 U8 [- k3 z6 }: \
  258. 258 static char *print_array(cJSON *item,int depth,int fmt);
    # Y' y# v$ d. E9 }
  259. 259 static const char *parse_object(cJSON *item,const char *value);* h8 P4 n# z) x
  260. 260 static char *print_object(cJSON *item,int depth,int fmt);9 G- P  p7 w' `! a. W( K+ s( m! s3 H
  261. 261
    , x) \% u% q5 q! \
  262. 262 /* Utility to jump whitespace and cr/lf */" d- R; L' D! I& k4 F' [4 n
  263. 263 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}, d* z" q, Z9 J% O: X. f" I% j
  264. 264
    7 R7 T4 `, h: {4 I1 t- `( j: I& I) z
  265. 265 /* Parse an object - create a new root, and populate. */
    # Y% t/ I4 a5 i) A5 d9 e
  266. 266 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
    2 n! C/ x. \# ?5 w: Z
  267. 267 {
    9 ?$ x/ h( N" W' l: K9 N/ Q" ]
  268. 268     const char *end=0;2 [8 A" A4 i: H$ p
  269. 269     cJSON *c=cJSON_New_Item();
    4 ?& n: k/ D2 Z) x
  270. 270     ep=0;- Q! b: R2 @$ Y/ y% \& B. _: b
  271. 271     if (!c) return 0;       /* memory fail */
    0 Y7 u: \$ C; E- ^
  272. 272
    ! S! z" K4 [+ w3 b3 m% P
  273. 273     end=parse_value(c,skip(value));
    ; u( W( i9 ?- {6 p4 g" X. J' }
  274. 274     if (!end)    {cJSON_Delete(c);return 0;}    /* parse failure. ep is set. */
    $ e0 t0 c' x" x; i+ ?/ ^
  275. 275 5 b8 j, }' C' t" Y
  276. 276     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */. h8 g: u; Y  o
  277. 277     if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
      \8 o9 A& i7 d' S* ?2 j
  278. 278     if (return_parse_end) *return_parse_end=end;
    ; F8 \5 B$ ]) g
  279. 279     return c;. N0 d8 y8 Z1 V" w4 ]) g! o+ T
  280. 280 }
    7 ]3 z& c, g8 @$ v( z3 U& W
  281. 281 /* Default options for cJSON_Parse */9 z1 F$ [1 a5 r. p8 b8 R% _0 U
  282. 282 cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
    2 f" A2 V7 u6 O8 m* j! p& N: g$ u& D
  283. 283
    ( r" }, @- z3 c
  284. 284 /* Render a cJSON item/entity/structure to text. */
    , ?2 a: a5 l; F  X/ E5 {; q0 {) o
  285. 285 char *cJSON_Print(cJSON *item)                {return print_value(item,0,1);}. ^/ q1 A: e% D5 ?. F
  286. 286 char *cJSON_PrintUnformatted(cJSON *item)    {return print_value(item,0,0);}
    8 [2 }2 A2 p/ G( M+ N5 y/ }+ [
  287. 287
    4 }& V  w1 @; m6 M  [1 u& X
  288. 288 /* Parser core - when encountering text, process appropriately. */% u4 j. M# K/ c5 {  h6 @1 m4 C
  289. 289 static const char *parse_value(cJSON *item,const char *value)
    & _. Z# E5 J2 q' s5 ~$ J
  290. 290 {! B+ a$ V- S+ g
  291. 291     if (!value)                        return 0;    /* Fail on null. */
    % `- r3 x/ n4 j  _! S/ N- G
  292. 292     if (!strncmp(value,"null",4))    { item->type=cJSON_NULL;  return value+4; }
    - s, W+ q4 N8 Q1 ~
  293. 293     if (!strncmp(value,"false",5))    { item->type=cJSON_False; return value+5; }
    & ^( ^/ G6 T- z+ {
  294. 294     if (!strncmp(value,"true",4))    { item->type=cJSON_True; item->valueint=1;    return value+4; }" S& c$ d  T1 G$ F9 ?3 z5 T
  295. 295     if (*value=='"')                { return parse_string(item,value); }
    " P7 r9 \" G1 M) r( R- l- p
  296. 296     if (*value=='-' || (*value>='0' && *value<='9'))    { return parse_number(item,value); }: {  o6 k! a, @0 R6 [7 K! G
  297. 297     if (*value=='[')                { return parse_array(item,value); }
    * k8 x  G/ K' n. L3 ?: ?
  298. 298     if (*value=='{')                { return parse_object(item,value); }
    # m2 J" ]; A: E8 K
  299. 299 # P$ h5 W7 S6 a' S4 ~
  300. 300     ep=value;return 0;    /* failure. */
    2 _0 y$ Z0 \8 |" q0 F' q
  301. 301 }2 W3 ?# C) w2 y; X, E, a$ V
  302. 302
    4 [; t; I- I5 B$ H2 {/ j0 W3 W* Z5 S
  303. 303 /* Render a value to text. */) F* G+ |" \1 _# F: k7 ~# `  [
  304. 304 static char *print_value(cJSON *item,int depth,int fmt)
    8 [9 @/ s# M' F) f3 p$ S) l
  305. 305 {$ v/ O9 E3 Q9 O6 Y
  306. 306     char *out=0;
    ) E* r& a6 n9 T9 T: O! U  S% ^
  307. 307     if (!item) return 0;
    + ~# X& U6 `, _
  308. 308     switch ((item->type)&255)$ t0 F/ G  }  g  r- E: o7 [! u! P
  309. 309     {; `5 K. v0 u3 U" I# W
  310. 310         case cJSON_NULL:    out=cJSON_strdup("null");    break;3 g1 a( R) e  J( N8 R( ~, `6 m; y
  311. 311         case cJSON_False:    out=cJSON_strdup("false");break;' y* G# ?% P7 C  ?7 {" b, P
  312. 312         case cJSON_True:    out=cJSON_strdup("true"); break;# \* _" R% }/ ]4 x
  313. 313         case cJSON_Number:    out=print_number(item);break;& V8 w9 b  O/ m% r0 C, b
  314. 314         case cJSON_String:    out=print_string(item);break;/ V8 E2 f6 }) p2 m
  315. 315         case cJSON_Array:    out=print_array(item,depth,fmt);break;0 g+ x( K5 Y5 _) t4 J. ]* L
  316. 316         case cJSON_Object:    out=print_object(item,depth,fmt);break;
    2 x: d0 t# V3 ?. }4 s* D# P$ `
  317. 317     }7 n  M1 e' q* {' S
  318. 318     return out;
    0 }/ Q+ N% @3 p* b2 l$ u
  319. 319 }
    3 P4 B! K2 g0 x4 [# D
  320. 320
    1 W# S* U9 z4 o0 c, M3 D# V
  321. 321 /* Build an array from input text. */' J- l1 K0 K4 f
  322. 322 static const char *parse_array(cJSON *item,const char *value)
    2 T# k. G/ s* C* u
  323. 323 {
    6 \3 ~  r% m$ {. T
  324. 324     cJSON *child;
    1 V' V$ q' W; l
  325. 325     if (*value!='[')    {ep=value;return 0;}    /* not an array! */
    8 a6 h0 V& h' Y7 N
  326. 326
    2 ~' Y% P& [: F) V0 c
  327. 327     item->type=cJSON_Array;/ j- g# @, w" I+ u' ]
  328. 328     value=skip(value+1);
    - C/ J9 U- d: A4 I9 M
  329. 329     if (*value==']') return value+1;    /* empty array. */
    / ?' t# p# T4 O6 P3 z
  330. 330
    , y" I# I  ^. T, A3 J6 G
  331. 331     item->child=child=cJSON_New_Item();3 D9 b! j! _8 `+ c7 k
  332. 332     if (!item->child) return 0;         /* memory fail */" j1 E' d0 W' T  S" n) I0 ?0 ^
  333. 333     value=skip(parse_value(child,skip(value)));    /* skip any spacing, get the value. */
    2 Q: m4 X) o$ m5 L# Q% p% [
  334. 334     if (!value) return 0;
    ; O3 S7 x% s& D
  335. 335
    ; Y4 r$ v9 Q+ g( R8 ^  [* m
  336. 336     while (*value==',')
    / ?3 J* S* Y# x& ~8 [: ^  X
  337. 337     {% C5 o$ M+ l* h0 y
  338. 338         cJSON *new_item;
    0 h- V& K3 w: Y( [+ c6 d
  339. 339         if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */9 z5 V/ p4 H) P1 e* z2 Q
  340. 340         child->next=new_item;new_item->prev=child;child=new_item;4 V) D) y: S0 ?, p9 l# u: x
  341. 341         value=skip(parse_value(child,skip(value+1)));
    : f& ?: l1 N: x& u! M$ C
  342. 342         if (!value) return 0;    /* memory fail */) j+ U/ K# Y0 j* M. b( G
  343. 343     }2 K. T3 i. ?: a7 k
  344. 344
    ) j( y; c$ I, V; a+ P* i" k
  345. 345     if (*value==']') return value+1;    /* end of array */
    ( `; e( S5 N) k/ |
  346. 346     ep=value;return 0;    /* malformed. */5 V. w  D- ]: ?8 K" O% \- e
  347. 347 }
    9 K4 Q  z: Q- v3 }- O3 m  I" @# w
  348. 348 / p& L4 F5 r1 \4 T0 c, D
  349. 349 /* Render an array to text */
    ! x9 \4 t& y1 g& _; ]# Q3 i4 }
  350. 350 static char *print_array(cJSON *item,int depth,int fmt)
    - {8 x# d8 e! b! e7 d
  351. 351 {+ U! V+ a  j; b0 w% X- r4 T5 i( A
  352. 352     char **entries;
    3 _" x" T4 ~( w7 M
  353. 353     char *out=0,*ptr,*ret;int len=5;5 @! \/ d1 F+ f3 v' W, f
  354. 354     cJSON *child=item->child;  }% C* N& Y# p) S4 N! _* G
  355. 355     int numentries=0,i=0,fail=0;3 I& l, }# t( B& _* e* A% W1 u( R
  356. 356     
    $ ]9 h# `( v0 c7 z/ L
  357. 357     /* How many entries in the array? */% [( l, k  M/ m( P# n1 r# m; P* p
  358. 358     while (child) numentries++,child=child->next;) S  f" F/ q, J3 V* I/ |
  359. 359     /* Explicitly handle numentries==0 */' u0 f/ N6 @# X2 C2 z, A- W
  360. 360     if (!numentries)8 Z/ F; p& _" V# S/ }
  361. 361     {% W8 g/ A4 d" E. t% O9 }
  362. 362         out=(char*)cJSON_malloc(3);
    " L9 C! Z& o' H! w$ C9 d8 W$ B6 v
  363. 363         if (out) strcpy(out,"[]");  |6 n/ R' ]2 v' {) K3 c
  364. 364         return out;
    , E- ^' A' ~/ X& C4 E8 I. L1 K7 i
  365. 365     }- b2 g2 n# {4 l5 d, v# h& N* O
  366. 366     /* Allocate an array to hold the values for each */& V/ T  s$ d! W3 A3 ~' T9 P* Q+ N
  367. 367     entries=(char**)cJSON_malloc(numentries*sizeof(char*));
    1 e3 m- p0 N( t5 H+ ?6 p! S- Q
  368. 368     if (!entries) return 0;$ T. D" E- p/ I# Y' q0 B7 f
  369. 369     memset(entries,0,numentries*sizeof(char*));9 p1 H, @7 X( l$ e( ~6 `
  370. 370     /* Retrieve all the results: */0 [+ U6 D7 g& M5 H4 T8 F% P- p
  371. 371     child=item->child;
    1 T) Z! ~7 X6 l+ i. E, {- b
  372. 372     while (child && !fail)) r( L- E9 }6 @7 C& \
  373. 373     {% _/ F3 f: e( n
  374. 374         ret=print_value(child,depth+1,fmt);
    ' L+ o  W$ W' ]& i* C* j7 h: ?* z, C" r
  375. 375         entries[i++]=ret;
    % \# _/ T, e# W1 s# K$ M6 J1 Y% {4 y
  376. 376         if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;( F) M, k" }# \
  377. 377         child=child->next;
    & |4 ]( {# z4 }9 W/ C/ k9 F6 j6 ?2 ?
  378. 378     }
    6 C7 f( y$ N: {8 L; _4 q* c6 D
  379. 379     ) S. c* `8 ]( j4 w
  380. 380     /* If we didn't fail, try to malloc the output string */
    0 K6 f; h4 o1 i7 l, s  ^) e* I
  381. 381     if (!fail) out=(char*)cJSON_malloc(len);* c  k1 n. P& z& w$ w' L
  382. 382     /* If that fails, we fail. */
    7 L5 {- g. l9 f
  383. 383     if (!out) fail=1;
    ! w4 M$ F( `0 f
  384. 384
    9 s4 l' H1 a' [5 o
  385. 385     /* Handle failure. */
    ! W- N0 g8 V( m9 ^( I8 t, s
  386. 386     if (fail)
    , w/ G9 m: A0 D' Z8 e0 P1 B$ q5 g
  387. 387     {( w7 d' a' Y! f" E( b
  388. 388         for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
    / \, C  \( o4 Z( A! v! r
  389. 389         cJSON_free(entries);
    6 i3 |2 j& O. D; c' O. z$ b+ e
  390. 390         return 0;
    - O7 I  l; [; r6 j+ M, F
  391. 391     }
    " N- Z' |5 {& g3 X! p2 h
  392. 392     $ j3 `& k5 y# T0 m& y  t7 a) E5 [
  393. 393     /* Compose the output array. */" u7 ~" @$ A- ]5 k' W  J: V0 Q
  394. 394     *out='[';
    . f& N4 x3 G, m2 r
  395. 395     ptr=out+1;*ptr=0;) ^# J' d1 J  Q( c7 |
  396. 396     for (i=0;i<numentries;i++)
    + w! o: u6 I, `) h/ k
  397. 397     {
    - o9 e9 F! H. [  H( L
  398. 398         strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);, e; G1 \6 S0 J' \
  399. 399         if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}/ D9 B1 V1 s8 K" u
  400. 400         cJSON_free(entries[i]);7 w: l/ ~6 D) X( f6 C& n6 u
  401. 401     }5 Z" e0 N: i1 }, z5 Z2 R
  402. 402     cJSON_free(entries);6 x0 o9 L6 S  @( T2 |
  403. 403     *ptr++=']';*ptr++=0;4 t  i, x$ w2 V5 C
  404. 404     return out;    , H% W+ h3 V+ E
  405. 405 }; n# f: B, p8 C5 h6 ?
  406. 406
    0 T6 b- y, k* ]- E7 k, o2 y4 K* f
  407. 407 /* Build an object from the text. */
    + O3 e! c) f( w: G4 V* w% Z
  408. 408 static const char *parse_object(cJSON *item,const char *value)" D% e# Y' o) H8 m/ v
  409. 409 {
    5 S7 ~1 l$ J% Q  G, g, k$ u  ~
  410. 410     cJSON *child;
    5 b& i2 l% Q7 Y' S$ y7 T! u  Q
  411. 411     if (*value!='{')    {ep=value;return 0;}    /* not an object! */
    - c' h  y) N4 j8 Z
  412. 412     
    . Q* O0 f. Z3 ^1 l
  413. 413     item->type=cJSON_Object;
    2 a& h9 ?6 |! \& M$ W! W
  414. 414     value=skip(value+1);0 @6 E- z) g% W( g  t' n, |$ _# a
  415. 415     if (*value=='}') return value+1;    /* empty array. */
      q* X' c( C$ `6 ]! C) ]
  416. 416     
    ; m9 h$ Q; P6 H1 U) O0 ]$ F  {6 |" q
  417. 417     item->child=child=cJSON_New_Item();/ a( m9 m; D5 q% _
  418. 418     if (!item->child) return 0;% O2 i4 X, i+ |" h# s  q( [
  419. 419     value=skip(parse_string(child,skip(value)));* l+ W9 u$ ?& m1 k7 }* y6 u8 g# y- c
  420. 420     if (!value) return 0;
    , ~  y4 w8 ]5 R  I
  421. 421     child->string=child->valuestring;child->valuestring=0;- ~% Z  y: I: Q
  422. 422     if (*value!=':') {ep=value;return 0;}    /* fail! */
    3 G2 i$ N5 \; M, @% s9 z. `4 P
  423. 423     value=skip(parse_value(child,skip(value+1)));    /* skip any spacing, get the value. */5 F) ?+ d5 Q& X  t  u3 q) ]8 ~- @
  424. 424     if (!value) return 0;$ g  s9 Y) R' \1 V: c
  425. 425     
    + I* u- r/ |) v- h
  426. 426     while (*value==',')
    & ?8 L/ ]3 J# _+ ]# T
  427. 427     {
    ! R0 x- z( q7 m9 p* a/ k
  428. 428         cJSON *new_item;$ F6 L2 j6 j. [& n$ D$ k$ z
  429. 429         if (!(new_item=cJSON_New_Item()))    return 0; /* memory fail */
    2 v% l" M/ `  m  V
  430. 430         child->next=new_item;new_item->prev=child;child=new_item;
    % h) P" Q; a1 y, t( [
  431. 431         value=skip(parse_string(child,skip(value+1)));2 o+ t) G& B/ P
  432. 432         if (!value) return 0;+ b" z9 A. h9 ^$ O, J5 w
  433. 433         child->string=child->valuestring;child->valuestring=0;/ e( |+ j4 m0 o# z4 S! j
  434. 434         if (*value!=':') {ep=value;return 0;}    /* fail! */* j6 ^; T7 [( `7 P, Q; [  ^
  435. 435         value=skip(parse_value(child,skip(value+1)));    /* skip any spacing, get the value. */
    * ]7 Q/ J/ b3 F  f/ I6 w; J
  436. 436         if (!value) return 0;% b1 m1 Z5 F) P# ~  n
  437. 437     }
    9 S& M8 {9 I1 ?6 l/ E2 d% y
  438. 438     
    % }% [2 g+ h/ l6 U4 I
  439. 439     if (*value=='}') return value+1;    /* end of array */8 s: ~! N3 b) _- ]
  440. 440     ep=value;return 0;    /* malformed. */* ~% f. D. A5 V* \
  441. 441 }
    . D3 L) q# {$ Q
  442. 442
    * ~. G( B/ w8 O
  443. 443 /* Render an object to text. */
    : B/ B& J: J/ r+ m: d( o
  444. 444 static char *print_object(cJSON *item,int depth,int fmt)
    % O( e) }$ j" _" Q& I
  445. 445 {
    ( S5 A, V1 c5 d  ^8 z3 X8 J4 W
  446. 446     char **entries=0,**names=0;% U4 _1 [' e1 T+ B
  447. 447     char *out=0,*ptr,*ret,*str;int len=7,i=0,j;$ N3 D$ G( i" S, O7 P3 i
  448. 448     cJSON *child=item->child;
    + e/ \2 }2 M! u7 {. P" @. z. f" r
  449. 449     int numentries=0,fail=0;8 {4 S# D. O0 D3 `, j* P
  450. 450     /* Count the number of entries. */
    1 g+ T0 d! c& ^! ~  O7 V. t5 d
  451. 451     while (child) numentries++,child=child->next;
    6 W" o- ]  B0 D: ?9 I8 p$ T) K6 p6 _# Q
  452. 452     /* Explicitly handle empty object case */3 M( J# Z0 g# q9 }3 q
  453. 453     if (!numentries)( Q9 f* `6 k! Q8 P$ Y. D+ c6 w3 e
  454. 454     {
    6 [: p" |6 G/ t* ?7 o
  455. 455         out=(char*)cJSON_malloc(fmt?depth+4:3);# B) Y* h# M# i- ?  c; e
  456. 456         if (!out)    return 0;& l* G6 L+ I) F, M2 X
  457. 457         ptr=out;*ptr++='{';
    / N& A+ L, Z; H  K
  458. 458         if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}. A. t  L1 e5 e) N/ K& s' F" n
  459. 459         *ptr++='}';*ptr++=0;& v: V5 r5 f8 k$ k
  460. 460         return out;
    9 [0 B" t6 O/ k+ C" Z3 H
  461. 461     }# Y# [3 b8 r% C7 u9 {- K
  462. 462     /* Allocate space for the names and the objects */8 p6 g4 u1 N. ~+ M
  463. 463     entries=(char**)cJSON_malloc(numentries*sizeof(char*));8 f! t' r) o8 r, z
  464. 464     if (!entries) return 0;
    + h, _( s' f2 K2 \6 W
  465. 465     names=(char**)cJSON_malloc(numentries*sizeof(char*));
    - J+ S  p! l% X/ |6 k
  466. 466     if (!names) {cJSON_free(entries);return 0;}
    - m: q" \9 T& b  J+ h
  467. 467     memset(entries,0,sizeof(char*)*numentries);( }, B! v2 j1 [2 |" T
  468. 468     memset(names,0,sizeof(char*)*numentries);$ \7 _" ~, o/ z9 \
  469. 469 ' w1 I6 |6 @* k# \; S
  470. 470     /* Collect all the results into our arrays: */
    1 V  R/ R, r0 q4 R+ k
  471. 471     child=item->child;depth++;if (fmt) len+=depth;# O2 U7 n/ z& ~
  472. 472     while (child)
      U9 B! Q( B+ Y5 D
  473. 473     {& N+ B& |% H! j( f0 n+ _
  474. 474         names[i]=str=print_string_ptr(child->string);
    & {* |$ o& Z, X$ R, U+ U) B- d
  475. 475         entries[i++]=ret=print_value(child,depth,fmt);
    5 p; F8 i6 M& r) ?' D3 W
  476. 476         if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;3 i% N- h1 _& D
  477. 477         child=child->next;( V( ?( C9 y( p0 U
  478. 478     }6 M4 X* x+ m/ W& i0 j. T; ^8 \
  479. 479     , V& E5 U4 W) ~
  480. 480     /* Try to allocate the output string */
    " I/ m; Z" \6 u8 L9 E
  481. 481     if (!fail) out=(char*)cJSON_malloc(len);
    " [3 N" e( X6 {" Q" @9 w
  482. 482     if (!out) fail=1;
    . Z; x% ?9 l/ g  V' S
  483. 483 6 P2 \8 s* B' z! M$ s+ d4 ~( |
  484. 484     /* Handle failure */2 U# S1 c% E% ^- ^- Y5 q
  485. 485     if (fail)
    " a, O+ A) b, D+ x
  486. 486     {
    / E# @$ i7 ?# D7 a
  487. 487         for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}( @' c9 a0 }: }1 }% P  V
  488. 488         cJSON_free(names);cJSON_free(entries);
    # G$ J4 f$ L& v0 [4 d9 S# m8 o
  489. 489         return 0;
    7 e8 M% s1 z# G4 Y$ G
  490. 490     }
    4 m3 Y7 e. l3 v* Y( m% T9 T+ b4 J
  491. 491     6 Q5 o( E7 T7 B. D( L5 ^& C9 p
  492. 492     /* Compose the output: */" i3 c  I( c" E! P! g% j
  493. 493     *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
    / K* I, F0 y: K4 S' ^# B0 M
  494. 494     for (i=0;i<numentries;i++)* g( x! p2 u8 d7 L7 S
  495. 495     {
    5 D6 w* `$ d$ b2 L
  496. 496         if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
    1 ^; K# O& p9 O! |; K2 f
  497. 497         strcpy(ptr,names[i]);ptr+=strlen(names[i]);3 n0 f# W# q8 O. u9 C) M
  498. 498         *ptr++=':';if (fmt) *ptr++='\t';
    ' \  a* r7 ~. r. e
  499. 499         strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
    & ~- b' \" a6 E* K/ F  E2 s
  500. 500         if (i!=numentries-1) *ptr++=',';
      L6 C, }' u2 `; s+ N  i8 [
  501. 501         if (fmt) *ptr++='\n';*ptr=0;
    & u  f; \/ C- B, z' K5 M9 a
  502. 502         cJSON_free(names[i]);cJSON_free(entries[i]);
    1 A$ f. r, _6 n
  503. 503     }. I0 a3 B/ x& ~* T' _" S7 v
  504. 504     
    % U3 x2 [( d; l. x
  505. 505     cJSON_free(names);cJSON_free(entries);9 Z& |4 _2 L6 L5 ]# a5 q  ]
  506. 506     if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
    0 @8 V4 @6 x6 J, v0 E4 i  X/ v; U" y
  507. 507     *ptr++='}';*ptr++=0;
    5 [0 g% f8 P- g8 d5 s+ h
  508. 508     return out;    : ~4 ?" f8 D6 T/ c4 I  ~; c/ T/ f
  509. 509 }
    - J3 M2 o7 q, z1 w
  510. 510 ) ]0 U; g* i. u' I" @% t; ?
  511. 511 /* Get Array size/item / object item. */
    . a; H! S- t- O0 \- `; ^5 Z
  512. 512 int    cJSON_GetArraySize(cJSON *array)                            {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}! J5 H1 Q" h. n- {( J7 k1 s6 r
  513. 513 cJSON *cJSON_GetArrayItem(cJSON *array,int item)                {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
    ) C2 I$ ~0 N4 C1 [& ]# n/ R  ~
  514. 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;}: ~7 x8 }& n# H( ^
  515. 515
    8 _0 A0 m3 T0 U# S" e8 q
  516. 516 /* Utility for array list handling. */: h& W- H5 A4 I
  517. 517 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}0 ]9 h3 m6 {0 D+ M
  518. 518 /* Utility for handling references. */
    5 ~' C( S, m: J  o" `
  519. 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;}
    ( p, |5 B8 l% S
  520. 520
    * @  F2 ^: a5 H) @5 p# g% R1 f$ Z
  521. 521 /* Add item to array/object. */
    1 v9 I/ h' g0 J: A
  522. 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);}}
    " b  w) N) y5 K: Z
  523. 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);}5 H- q+ Z$ X6 e2 H
  524. 524 void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                        {cJSON_AddItemToArray(array,create_reference(item));}
    # g1 Y! F  ]7 f; X7 E8 }
  525. 525 void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
    & }8 ~4 j# |) V
  526. 526 . A2 ~5 S6 [6 ]! x; Q5 E
  527. 527 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)            {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
    ( x, ]! O7 h4 k8 U6 b, t- L
  528. 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;}
    + }8 L# w- X" T, u+ G" _
  529. 529 void   cJSON_DeleteItemFromArray(cJSON *array,int which)            {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}: y  i/ Q/ K7 X5 r. T% }4 H
  530. 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;}
    : T# m% N9 m2 A% U
  531. 531 void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
    " ?7 C( y" m1 K
  532. 532
    " D$ d8 Q) y/ L3 w8 i
  533. 533 /* Replace array/object items with new ones. */
    3 \) N6 K7 J2 N& U* H1 F, {. k2 k
  534. 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;. s8 N8 s9 A4 d$ q/ [0 l/ j6 ~0 Q
  535. 535     newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;6 G$ K' `7 `! T8 ~. [# Y4 m
  536. 536     if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}" G: Q' e- j* k. W3 S$ a
  537. 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);}}  U* W/ Q! f9 u' l) g$ k' C5 O/ A
  538. 538
    & }* r( {! N- [' J  T
  539. 539 /* Create basic types: */
    ) ^% l9 |; F9 V" q
  540. 540 cJSON *cJSON_CreateNull(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
    # g5 x* V# L$ y6 w$ R- G3 c& p
  541. 541 cJSON *cJSON_CreateTrue(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}7 O8 G- Z% T0 X. r) Q
  542. 542 cJSON *cJSON_CreateFalse(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}, s2 T4 f, Q& w9 [( d
  543. 543 cJSON *cJSON_CreateBool(int b)                    {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}, u3 b$ @  `  |0 O
  544. 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;}
    : h) Q2 R. |% W' r: i
  545. 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;}. D% G! w$ T4 g3 ^4 S
  546. 546 cJSON *cJSON_CreateArray(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}2 Q7 s' X4 D4 }4 j- A; Z
  547. 547 cJSON *cJSON_CreateObject(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
    + A/ Z- ^  x2 F
  548. 548
    3 J/ U; F' D. o
  549. 549 /* Create Arrays: */
    9 j* v. h( K$ b7 ~( e
  550. 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;}
    6 L* |+ l/ ]3 S* [
  551. 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;}
    + T( g; v( t0 I1 X& s3 m% K! ?4 G
  552. 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;}
    9 F: D- G, m9 Q& [! b8 B
  553. 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;}9 n, |- [! _4 X; j( E; q
  554. 554 6 R( `; f* ?+ g- X7 k3 U3 M5 W
  555. 555 /* Duplication */
    8 i7 a& a" ^7 p( Y
  556. 556 cJSON *cJSON_Duplicate(cJSON *item,int recurse)
    4 }+ u$ V  a! \$ E9 x! A- t" N
  557. 557 {) s3 g; O; s7 |; L/ J
  558. 558     cJSON *newitem,*cptr,*nptr=0,*newchild;% m5 @9 _& \5 Y: p9 c  w2 ~% }
  559. 559     /* Bail on bad ptr */
    - k6 Y+ g) A, G3 m/ i+ d
  560. 560     if (!item) return 0;4 h: U8 j* a* L+ B5 `* w) l( T
  561. 561     /* Create new item */
    . I. B; O) I- o/ F$ x- {, u
  562. 562     newitem=cJSON_New_Item();+ s/ w! b! P2 l0 H4 L! k6 }$ G
  563. 563     if (!newitem) return 0;
    8 B* S& j* i2 J5 j, O+ c) D
  564. 564     /* Copy over all vars */8 k% ]" M4 H" T% W0 L3 o* Y& V. Q$ o
  565. 565     newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;% `) J( a, I" v' U
  566. 566     if (item->valuestring)    {newitem->valuestring=cJSON_strdup(item->valuestring);    if (!newitem->valuestring)    {cJSON_Delete(newitem);return 0;}}% Y, S( p9 i1 L! C& Z
  567. 567     if (item->string)        {newitem->string=cJSON_strdup(item->string);            if (!newitem->string)        {cJSON_Delete(newitem);return 0;}}
    6 @& P0 t' R) E2 A
  568. 568     /* If non-recursive, then we're done! */
    2 F1 g3 K. Q! [! x
  569. 569     if (!recurse) return newitem;7 l" a+ o! X2 j9 p. t$ r  s
  570. 570     /* Walk the ->next chain for the child. */# n7 c6 _$ ]' N3 K9 I: n) N+ m
  571. 571     cptr=item->child;
    + H) n% C9 y8 }2 |% y$ z
  572. 572     while (cptr)2 R; E. L! n8 L
  573. 573     {- ]9 F  N9 i0 P
  574. 574         newchild=cJSON_Duplicate(cptr,1);        /* Duplicate (with recurse) each item in the ->next chain */% q" N7 s& y: d$ Q
  575. 575         if (!newchild) {cJSON_Delete(newitem);return 0;}
    0 I( v- |& ~! a9 E! D7 ]( ]
  576. 576         if (nptr)    {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}    /* If newitem->child already set, then crosswire ->prev and ->next and move on */1 L' N6 {+ z  F2 ]( S; U5 c! t
  577. 577         else        {newitem->child=newchild;nptr=newchild;}                    /* Set newitem->child and move to it */
    ) G9 h: @7 M0 s8 c( C3 e
  578. 578         cptr=cptr->next;  J: F3 t! l3 x
  579. 579     }
    4 F& d& G( z# {0 P  Y2 z1 Z
  580. 580     return newitem;
    4 s) n7 a' w- Y. k. r8 x
  581. 581 }' Z' |8 D* N) N. w$ k) s0 u
  582. 582 ; P3 p8 Q  x9 B
  583. 583 void cJSON_Minify(char *json)5 ?8 [4 X0 b$ |
  584. 584 {
    ; f4 W! B( M' D) w8 Z+ ?
  585. 585     char *into=json;4 ]- Z4 _( C2 W( {# B3 J
  586. 586     while (*json)& p8 X1 \& r* n8 r; V+ m
  587. 587     {
    ) D! Z! r7 |# j( Y. {& }5 _. t: n
  588. 588         if (*json==' ') json++;& U' c+ I, S+ ?* _# [* w( I0 n' ^- o
  589. 589         else if (*json=='\t') json++;    // Whitespace characters.
    - R7 O, T: q: h6 z2 q9 N* L5 ^
  590. 590         else if (*json=='\r') json++;# Y/ H) H- ?% C. A$ O% h
  591. 591         else if (*json=='\n') json++;
    ) B/ b8 {8 g! G, H2 ]: Z
  592. 592         else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;    // double-slash comments, to end of line.
    ( ?" D" [* r5 {
  593. 593         else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}    // multiline comments.
    * W8 M' `6 r- G( T7 }/ v
  594. 594         else if (*json=='"'){*into++=*json++;while (*json && *json!='"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are " sensitive.
    9 F) q+ {8 A- J. ^; Q, M4 A8 c
  595. 595         else *into++=*json++;            // All other characters.
    8 S8 R" \) c, k* f
  596. 596     }
    2 {) Y" q( R+ `: p8 \
  597. 597     *into=0;    // and null-terminate.
    ; b+ V' f; }8 p; b8 K2 ^
  598. 598 }cJSON.h内容如下+ F; ]9 Y6 E' _  U7 T
  599.   1 /*
    5 I* J7 U6 A2 ?2 U8 G9 Z/ e2 `
  600.   2   Copyright (c) 2009 Dave Gamble8 \& ^+ [) Y% V
  601.   3  
    ) ]7 T. h. W/ {& V( I  e
  602.   4   Permission is hereby granted, free of charge, to any person obtaining a copy
    " G7 N! a4 q( @: o% T
  603.   5   of this software and associated documentation files (the "Software"), to deal
      f9 T3 K# @+ w2 l2 p
  604.   6   in the Software without restriction, including without limitation the rights7 y  [( ~4 o4 H+ j' l, f0 @
  605.   7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell) y( D6 }9 }, V4 O6 g
  606.   8   copies of the Software, and to permit persons to whom the Software is0 g6 h: k, w& X" k: `& P% p
  607.   9   furnished to do so, subject to the following conditions:
    ; N: b0 J+ F  p6 B
  608. 10  
    ! o1 {! \1 A  ]4 ]; C  Z" r
  609. 11   The above copyright notice and this permission notice shall be included in# `. q( X; `3 o/ c$ y
  610. 12   all copies or substantial portions of the Software.& B: ~, A9 F* i0 a: F$ G
  611. 13  
    " _8 A9 c: D. Y2 x
  612. 14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    " P4 u: @! |( i1 i( t: A
  613. 15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,; `3 b. a5 W. {. C
  614. 16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2 W( e7 Z& ]7 ^7 [/ t
  615. 17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    , a1 \) i& Q3 B- A  ?: w) a) v
  616. 18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,6 V" y7 e0 |; e  l. I
  617. 19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN; s, M) S1 t! }; V; Q1 P
  618. 20   THE SOFTWARE.
    7 b& q7 O0 I2 q
  619. 21 */
    ' A6 U( B5 h) q- N+ P
  620. 22
      N+ k, Z$ w2 ]
  621. 23 #ifndef cJSON__h
    . p7 |6 `$ H% ^% h' `8 m4 N" L; t& l1 d
  622. 24 #define cJSON__h8 W" Q/ {( l3 p  W7 d
  623. 25
    9 ~, I) m; K- e) p  h$ v
  624. 26 #include <stddef.h>
    1 U- |6 ^7 H8 S( d0 ?
  625. 27 3 H1 U/ v% V& r% [# U
  626. 28 #ifdef __cplusplus2 K/ F5 r7 Q0 F( h& N: p8 |! l
  627. 29 extern "C") `$ {0 @  r( D4 l% Q, r! V/ e
  628. 30 {
      v4 e: ]. Z2 u$ x( H$ |6 @5 A  g
  629. 31 #endif
    ! K* {7 |& i- {; W) I5 x% ]4 J* [
  630. 32
    ' {9 I2 E  I+ h) ^) ]  ^% s
  631. 33 /* cJSON Types: */5 G5 Y/ G. b: u2 Q: r& M3 x
  632. 34 #define cJSON_False 0' b' s: ?8 n- N1 y, S( p
  633. 35 #define cJSON_True 1; Q. l( D4 G) {* J& z
  634. 36 #define cJSON_NULL 2
    1 w: H; r: i' d% S6 a
  635. 37 #define cJSON_Number 3# f- f/ \8 X# g& d4 w2 A* N
  636. 38 #define cJSON_String 45 f/ h, A: q# |. b$ \. q
  637. 39 #define cJSON_Array 5
    , B7 ~3 |* q! }" a/ e* z- F- S) ^$ k$ ?
  638. 40 #define cJSON_Object 6
    ) B! {  e; s# h2 @: J
  639. 41     : _! Q' T4 G# G" u( Q5 a2 T
  640. 42 #define cJSON_IsReference 2562 M% S4 f% T* F1 p! K0 e8 e
  641. 43 3 ]- D9 e6 w. E- G+ `
  642. 44 /* The cJSON structure: */' M, c4 F8 L/ s6 }7 g
  643. 45 typedef struct cJSON {
    * P' R5 {2 y$ k0 M
  644. 46     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    0 G0 }8 G% R. Q' `1 ?. K
  645. 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. *// N0 p6 s) E! ^) Y7 L4 d. a
  646. 48 5 G) [# p- w; K& c  v
  647. 49     int type;                    /* The type of the item, as above. */. \+ T, y9 ?9 m; z" z8 E/ t
  648. 50
    6 M( Q; c9 j  W3 D$ f: ?, f& D6 K
  649. 51     char *valuestring;            /* The item's string, if type==cJSON_String */
    . s. J, w0 ]/ y" O
  650. 52     int valueint;                /* The item's number, if type==cJSON_Number */& r% l* h5 Y' v2 x$ b& a7 g6 W
  651. 53     double valuedouble;            /* The item's number, if type==cJSON_Number */# T: ^  X3 g: f) V. v- p
  652. 54
    5 `9 w1 x7 M- Z! G
  653. 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. */
    / N) h$ c8 |" G' o& _
  654. 56 } cJSON;/ L- A; U& L- W+ b5 G
  655. 57
    0 A2 S4 ^+ [$ p1 u+ K" p
  656. 58   L6 i% U. T# L6 a& r6 l3 b4 Q
  657. 59
    - p% a' N$ `8 r
  658. 60 typedef struct cJSON_Hooks {" I  {' @$ |5 G% j* L
  659. 61       void *(*malloc_fn)(size_t sz);5 @" h9 h- o' }0 X% c' m
  660. 62       void (*free_fn)(void *ptr);: T5 n8 v  r" [, W9 z
  661. 63 } cJSON_Hooks;. S3 M$ w9 i) a8 ~% r  v7 ~" [
  662. 64 4 P% o' M! e, a) @
  663. 65 /* Supply malloc, realloc and free functions to cJSON */: N$ f! G: B/ u# R: j3 F! V' N
  664. 66 extern void cJSON_InitHooks(cJSON_Hooks* hooks);2 g/ y: f/ F2 b! t% o
  665. 67 9 G5 }0 `' Z/ V, T/ F' I
  666. 68
    9 v$ k* R* }* h% v
  667. 69 /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */# f" b& F" _% r
  668. 70 extern cJSON *cJSON_Parse(const char *value);
    0 v/ s. o' l8 b
  669. 71 /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
    , A; |- N$ T  j$ N) U4 S
  670. 72 extern char  *cJSON_Print(cJSON *item);$ O  i6 U( R% x! C
  671. 73 /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
    " B4 H/ p& C, n% Q7 p. {7 n3 t
  672. 74 extern char  *cJSON_PrintUnformatted(cJSON *item);
    - s% V( |; k: V4 g
  673. 75 /* Delete a cJSON entity and all subentities. */
    5 O" l$ C7 p# Q. F2 y
  674. 76 extern void   cJSON_Delete(cJSON *c);
    5 F' _' z3 G7 u9 \
  675. 77 6 m7 Q+ M  t* j' {4 i/ E& O
  676. 78 /* Returns the number of items in an array (or object). */
    / G4 B. q' R8 Y7 U; H
  677. 79 extern int      cJSON_GetArraySize(cJSON *array);
    2 J$ o0 p1 p& G9 G! W
  678. 80 /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */0 u: {7 Z$ k0 f
  679. 81 extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);2 e2 o. W1 N/ W5 h  z. s& X& p
  680. 82 /* Get item "string" from object. Case insensitive. */
    + I  K! ^8 B1 w  p" }& m4 W: S6 F
  681. 83 extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    8 W- z& B: c5 Q( c8 q8 H7 O
  682. 84 ) p4 b. w1 F& N* C% K
  683. 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. */
    : j+ G0 L4 x, N1 _
  684. 86 extern const char *cJSON_GetErrorPtr(void);
    ; c) f8 ~, I; `$ ^0 N% V
  685. 87     
    2 D5 T$ C8 {3 ?- w( I' s- U, L
  686. 88 /* These calls create a cJSON item of the appropriate type. */
    8 G0 ^6 m" y5 `2 j9 R/ G
  687. 89 extern cJSON *cJSON_CreateNull(void);3 Z+ H, b% |) O# S
  688. 90 extern cJSON *cJSON_CreateTrue(void);
    + F" q4 A' \" L" K8 g
  689. 91 extern cJSON *cJSON_CreateFalse(void);
    2 {) B  J& A5 I. i
  690. 92 extern cJSON *cJSON_CreateBool(int b);& w; ^! ^( z* `5 T% ?% o: D
  691. 93 extern cJSON *cJSON_CreateNumber(double num);
    7 E# }0 S8 g0 ], T  }# d
  692. 94 extern cJSON *cJSON_CreateString(const char *string);3 x8 U0 {. T3 b9 v# O# Q8 t
  693. 95 extern cJSON *cJSON_CreateArray(void);
    9 q. j( |* z& _9 ^* a2 ]
  694. 96 extern cJSON *cJSON_CreateObject(void);
    * ]. F8 \5 B  F+ Z
  695. 97
    , h& l& L7 t- U
  696. 98 /* These utilities create an Array of count items. */. o6 A5 L  s+ w* j
  697. 99 extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);$ Z  @/ a$ X0 d8 U, i' \  f
  698. 100 extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
    * v6 o! c" J' X* E
  699. 101 extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);" d, A: n5 @# W  D5 ^0 S! k& g
  700. 102 extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
    4 t% u, N7 o3 U7 ?% n: w" e
  701. 103 9 b3 z: B6 t. o; {5 B5 V) ?0 ], o/ H
  702. 104 /* Append item to the specified array/object. */! g. d5 z8 U, O
  703. 105 extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);3 K5 x- {, l! U- \( o, c
  704. 106 extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
    7 r' O' F0 }1 c4 Q  C8 z2 A7 ?
  705. 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. */
    7 F  ?/ e! g1 y& q" Z9 |, p
  706. 108 extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    ' ~9 g' ^6 W; f; i2 Y# j' f( A
  707. 109 extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
    2 ^9 o, r" g4 S2 Y
  708. 110
    ! B2 |8 T  K( n/ U
  709. 111 /* Remove/Detatch items from Arrays/Objects. */' X1 F! r% D& l
  710. 112 extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
    / m3 P6 h9 M4 ]6 }+ I' ], t! q
  711. 113 extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);( k. O' H) j" f0 |, T" J' L
  712. 114 extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
    3 H# C* W9 L9 [6 ?) s
  713. 115 extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);5 a/ W0 ?9 X. d
  714. 116     
    / N( w- F5 g0 C
  715. 117 /* Update array items. */+ b! S' N  z2 G4 h4 C: J
  716. 118 extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
    1 F9 [2 G1 s+ @! g4 J" L: n
  717. 119 extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);1 h  T- f6 Y+ t- q( g3 V
  718. 120 8 m: D: C3 S( b
  719. 121 /* Duplicate a cJSON item */" _' @; F& D5 N+ ?, q
  720. 122 extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);# r2 W% ?; j' P+ N. c
  721. 123 /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
    " ~5 R' V/ U: n) K
  722. 124 need to be released. With recurse!=0, it will duplicate any children connected to the item.* F* _+ F2 R1 B, _* E
  723. 125 The item->next and ->prev pointers are always zero on return from Duplicate. */
    " n5 A0 e! ]9 r6 u! Q
  724. 126
    1 j; V, a5 X' c  L6 J. o# n
  725. 127 /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
    ( ~, Y, B5 P6 e7 k
  726. 128 extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
    / J) Y$ X5 D, i' x( Z! h# s$ l
  727. 129
    & j3 u# Y' c! g( B: ]
  728. 130 extern void cJSON_Minify(char *json);5 O7 R1 c* `* n* r
  729. 131 % B0 k: o& {& o% S! N) ~& |: h0 B
  730. 132 /* Macros for creating things quickly. *// ]. G0 T8 L! Y( R# \
  731. 133 #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())
    ' F+ ^5 D9 [; W, [9 t4 a) X+ R7 `0 x
  732. 134 #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())8 @9 _+ k( u, [& y, X
  733. 135 #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse()): w4 M% m4 W" M: X) G( m$ ]! U' ]3 T
  734. 136 #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))9 u+ ~7 Y7 k7 Q! Z0 x! w2 [
  735. 137 #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
    + `, _6 }2 \& P* B
  736. 138 #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))+ O; J6 A1 z; p4 ]
  737. 139
    + L9 D8 j+ u5 w0 r$ _
  738. 140 /* When assigning an integer value, it needs to be propagated to valuedouble too. */
    / L" Q; Q4 f- _! A
  739. 141 #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))' F3 d( w( J3 J
  740. 142 % S8 Y2 A5 q" E# K" X6 m1 B3 _7 w
  741. 143 #ifdef __cplusplus) |% I+ x' z4 C+ _
  742. 144 }
    0 ?( k* K1 f4 y) [
  743. 145 #endif
    , p! B$ @' {" q: ?, V
  744. 146 # p" b- ]% S8 ^9 ?- j8 P# R
  745. 147 #endif
复制代码
  1. /*
    4 ^" F8 r" J( F* S. w' p
  2.   Copyright (c) 2009 Dave Gamble
    ' Q# P1 I! M1 O
  3. . [1 L7 k  a  Q. Y  A
  4.   Permission is hereby granted, free of charge, to any person obtaining a copy
    + K/ I# H: X- H# E. G
  5.   of this software and associated documentation files (the "Software"), to deal  l- j+ I& R7 P1 N. `3 V% y
  6.   in the Software without restriction, including without limitation the rights5 {( U4 K1 V3 O
  7.   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell& g3 g% A0 a% ^+ E7 N" W1 [
  8.   copies of the Software, and to permit persons to whom the Software is# e9 x1 B) [' \% q+ X$ o6 \
  9.   furnished to do so, subject to the following conditions:
    4 G# z  q4 @+ k
  10. ) e& S1 w1 g% w
  11.   The above copyright notice and this permission notice shall be included in
    * a% Y4 {7 k5 S
  12.   all copies or substantial portions of the Software.
      e9 o2 w. ~/ C1 S  ~* D

  13. 0 ?$ o/ u4 ]- v! C0 b6 q
  14.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    % W! Q7 f' n# d& ^2 @  h% j7 J( t$ k
  15.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,4 ]) ]" o: O- }2 |! \
  16.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE, d: C2 U" w1 @" C: @- u9 y
  17.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER2 s5 e9 }( {4 ]) L, t# k
  18.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,2 Y) R' l, X, u- {4 y7 F
  19.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* k+ g9 l6 o' p+ H3 c8 h9 `
  20.   THE SOFTWARE.9 O3 \0 }3 W- ^3 e# e- ?8 w
  21. */( ~8 |. [/ W+ |; Y6 K2 X6 K8 g
  22. , x, o! b" G. u* i. y
  23. #ifndef cJSON__h* h; I  y% H# _( w+ I
  24. #define cJSON__h
    ! B' @# y5 F- E- {2 d
  25. ! k7 `+ Y/ R) [
  26. #include <stddef.h>
    7 t: w( H$ W  [6 c' E9 `

  27. 9 O0 V* @, a" m5 r4 l* i
  28. #ifdef __cplusplus
    " O! N5 n! w* U3 i% C
  29. extern "C"! q0 g. _. f& i# U# x% W
  30. {
    / |1 J: R3 S# O" O" R
  31. #endif! X5 l( E( `' M. j3 ^

  32. 9 I4 B; b1 t4 X# W( c) G
  33. /* cJSON Types: */% c: D' D% A: z8 P3 n
  34. #define cJSON_False 0
    # ^9 K; q; b0 w1 Y/ T
  35. #define cJSON_True 1( G- P) `- Z$ P" W1 L
  36. #define cJSON_NULL 2
    4 J' H; ^" j7 h
  37. #define cJSON_Number 39 \3 k* k& a7 `# ~  p" s" d0 p. Y
  38. #define cJSON_String 48 {: H  p3 N" H! L3 L6 G+ g, b
  39. #define cJSON_Array 5
      }$ ^) U% j( K- z! U% p
  40. #define cJSON_Object 6
    2 ~; g9 R: J& z+ [% J: j3 U

  41. 9 k$ V+ k: f% K. o8 v
  42. #define cJSON_IsReference 256# S+ [5 @6 t; [! t9 W& K2 c
  43. 4 n. ^% M, W4 E# F3 \
  44. /* The cJSON structure: */
    . w& u6 J+ e6 S- l
  45. typedef struct cJSON {
    " x" \. Z- H- P! t" {2 x. s
  46.     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    0 Y$ p% u* Q2 F' k4 G  I" t- ~
  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. */# e* d0 E/ B  {6 ^! S
  48. % U0 v; G! \( F* U( {
  49.     int type;                    /* The type of the item, as above. */" k; n) V2 {/ C* @0 C5 a
  50. 9 a1 |2 s$ H; c$ q/ n9 k9 c) M0 t
  51.     char *valuestring;            /* The item's string, if type==cJSON_String */0 f7 u( Z# _* I, I
  52.     int valueint;                /* The item's number, if type==cJSON_Number */) M0 E, l- b* c  W8 A; _# l# G
  53.     double valuedouble;            /* The item's number, if type==cJSON_Number */* ~1 h4 B) h$ y/ P  J

  54. 6 J* v, }4 n, o0 E
  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. */3 f+ @3 v( e$ T+ Y( v
  56. } cJSON;! e6 M9 ?" r( d8 J0 j' |" X6 n+ o
  57. 6 K  Q6 k6 d# T. A- \' a

  58. 0 p5 Y" w- W3 g& {/ q6 O
  59. / O5 X; R+ l& C) h3 o& R
  60. typedef struct cJSON_Hooks {1 j$ ^, E0 J. T+ M% h
  61.       void *(*malloc_fn)(size_t sz);3 U7 W5 i* Y" k2 ^: T; P6 u7 R2 s# K
  62.       void (*free_fn)(void *ptr);4 D9 T$ Q0 |9 |  C
  63. } cJSON_Hooks;
    6 ^0 h/ L$ A4 A" x$ D
  64.   A  k6 F6 [, d+ T+ q# y7 z
  65. /* Supply malloc, realloc and free functions to cJSON */# V( e* z$ g  u, o% o$ m5 p4 w
  66. extern void cJSON_InitHooks(cJSON_Hooks* hooks);0 |! H7 z3 x# j

  67. / q4 i* u. F: A

  68. 9 E' l9 U- [9 K0 @- R6 n
  69. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
    + l8 Y5 I( V4 [/ Y
  70. extern cJSON *cJSON_Parse(const char *value);
    + t: l/ w0 @" p& V
  71. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */+ b6 {5 ^) m7 a; _1 b2 W
  72. extern char  *cJSON_Print(cJSON *item);
    # m' b/ o  K1 f9 t' m" G
  73. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */! Q: K; T. ?* R) ~
  74. extern char  *cJSON_PrintUnformatted(cJSON *item);6 {6 g) V; q/ L) V
  75. /* Delete a cJSON entity and all subentities. */
    5 ]4 n: _/ C/ R: p1 ]" j9 `9 F
  76. extern void   cJSON_Delete(cJSON *c);
    8 L0 D0 E9 T% M6 F; n9 R
  77. 4 w2 m; {" H' X, A4 C: E
  78. /* Returns the number of items in an array (or object). */: Z3 g) Y# T$ ~8 {6 g4 i3 s
  79. extern int      cJSON_GetArraySize(cJSON *array);; I8 _0 N" D: o3 O) u" V' M
  80. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */3 \+ S# \3 ^* I3 L6 @$ V, {- w
  81. extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
    8 e$ X9 n5 t- N" [4 ~0 H4 [8 n
  82. /* Get item "string" from object. Case insensitive. */- @3 g1 O9 @5 l, o+ {
  83. extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);6 b& F4 X% f) m# ]5 r& h# y' Y
  84. 8 \$ a2 p8 k/ A5 ~" m. z6 `7 q2 U
  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. */
    0 s/ x6 Q  A; R- q
  86. extern const char *cJSON_GetErrorPtr(void);
    # o$ n+ m/ i7 i. u( `( i+ \

  87. 5 P4 D4 v+ `9 Q6 b
  88. /* These calls create a cJSON item of the appropriate type. */# u/ y/ I+ s- M6 P
  89. extern cJSON *cJSON_CreateNull(void);9 \- j$ I5 c) k# X; g8 P$ t" n
  90. extern cJSON *cJSON_CreateTrue(void);: ^- B/ \% f8 [6 t
  91. extern cJSON *cJSON_CreateFalse(void);1 \. ]4 I, Z  j" Z- C
  92. extern cJSON *cJSON_CreateBool(int b);
    * k6 J) t+ S$ W) ]6 E% {
  93. extern cJSON *cJSON_CreateNumber(double num);9 \9 s+ c- G4 h. Z7 _. m
  94. extern cJSON *cJSON_CreateString(const char *string);# C4 I; _5 Y5 V8 l
  95. extern cJSON *cJSON_CreateArray(void);( I, @7 @0 k, z; e& y
  96. extern cJSON *cJSON_CreateObject(void);
    , p! z0 u1 W0 n8 N. r( G

  97. * }; H2 }4 H) f5 \) a$ r: \( P
  98. /* These utilities create an Array of count items. */
    - T6 F" V) P  T
  99. extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);6 P8 l( l- v. V
  100. extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);. M, @' l& ~; s  f& X
  101. extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);' G7 _  d% ~, {1 c6 v% @
  102. extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
    7 x3 C6 Z: p& K( H" v# T( X8 l/ r
  103. : h: I  g. O. I1 R0 S
  104. /* Append item to the specified array/object. */
    ' H- r1 v2 p1 G. B
  105. extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);" a/ S2 O% F# X5 d( f6 b  L) ~
  106. extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);  P: ^, o  t; d; q+ g
  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. */7 O# |9 L% s9 r( h- l# s  |2 M
  108. extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);/ v) y0 h6 N/ n7 n0 V' I- s
  109. extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
    & l5 J" N* x% g; s  K
  110. , b# |$ C+ f) X
  111. /* Remove/Detatch items from Arrays/Objects. */) j. z' m3 k- ]! d8 J0 E4 L; Q2 Q
  112. extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);* y# b! }8 o: Q- l5 \2 Y7 V$ `1 [$ |1 @
  113. extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
    ; M6 T! Y( o2 [+ [7 i4 s4 V5 Z2 Z
  114. extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);! v5 s. `! r' N8 D
  115. extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);* u9 N# ]' ?4 O9 R& T: \

  116. 4 Z3 M( ~, l. T; K
  117. /* Update array items. */3 q, T! M" \8 f( ?, w
  118. extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);6 U% J8 e: P2 h
  119. extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
    # z% F" k& {; ?% N/ ~, F) h% B
  120. 0 [# M  o. k, r, Z/ S
  121. /* Duplicate a cJSON item */
    3 f( X1 {" Z  d2 [! B- k' K; w+ ~
  122. extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);: Y" Q% U2 w/ e- h& `* x& E- J
  123. /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will' g5 Y# ?5 q( L9 [( i9 q) o
  124. need to be released. With recurse!=0, it will duplicate any children connected to the item.
      [4 K. E4 N. K- }5 m; n  s1 I  D
  125. The item->next and ->prev pointers are always zero on return from Duplicate. */. @- r3 a1 I! O8 w0 q

  126. ' z$ J4 M5 [* @6 J8 d, G
  127. /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */+ T+ x+ ~8 t% ?! t( [# H+ Y) ^# V
  128. extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);! ~5 Y3 J4 Z. A8 w. N5 \! v

  129. ; o: R' v6 ~9 u' ?
  130. extern void cJSON_Minify(char *json);
    % ?  V. k; t/ Y5 C, R3 b

  131. 5 p+ C( W& b5 O7 K4 c% e0 T5 {
  132. /* Macros for creating things quickly. */( J0 U0 ]9 d; K, W& B
  133. #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull()), H+ i5 ?; Q. c. m8 c6 D
  134. #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())4 `1 `. |$ J) D6 @2 o- {
  135. #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
    ( r# p6 p, x6 |  q1 Y# `
  136. #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
    9 h/ q: Q: H7 F4 ~7 A0 E
  137. #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
    / d' h% ^( I" g  F7 U
  138. #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
    , |) e6 j* X2 s5 O" {
  139. % Z* n1 M7 a! b, e# A) Z
  140. /* When assigning an integer value, it needs to be propagated to valuedouble too. */! w$ `- W! A% M& J* B
  141. #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))! Q  ^7 y6 U) i( i2 [

  142. ; `/ S1 ~2 Q$ a1 ^- E6 ^- S6 h
  143. #ifdef __cplusplus7 u8 ]/ o& Y. r( k& Z! P
  144. }
    ; o; c4 u, H2 g
  145. #endif
    # X5 N6 T% [1 s, i" z8 k' v6 [7 n  m& |
  146. 1 g4 Q7 c+ c5 K2 C' A% O0 x
  147. #endif
复制代码
下面是JSON数据的解析部分,简单说来就是对号入座。
  1. /**************************************************************************$ W9 F& Z0 h1 J0 N1 n0 u% @
  2. 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令0 F. x# c' Y$ R. _$ u1 n/ {
  3. 入口参数:JSON格式的字符串,
    5 M+ O' R8 n; V4 b
  4. 返回  值:指令类型
    # x7 d) @! t" l4 U
  5. 注    意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数
    2 ^8 a' b+ U: e9 @! l
  6. **************************************************************************/# w. S2 l9 n+ L2 O
  7. CommandType GetCommandFromServer(char * JsonDataFromSocket)
    ! U5 E& I7 b2 A7 Z) E
  8. {
    3 y7 ?) Y& `$ Y1 I

  9. : q4 s6 t: t4 l
  10. //  ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替
    " ?! m# ]! f2 y- y8 P8 `4 k
  11. 3 y& z" V+ S! _  v
  12. //    Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替9 v, U3 T0 g% e2 M  d) |8 L
  13.     CommandType cmdtype;
    3 f4 Y/ M& H3 e: R. V, w* |
  14.   RobotJSON_CMD_TypeDef json_cmd;% r& i  t* z7 [2 l
  15.     HelloJSON_Ack_TypeDef json_ack;
    * y# Y2 \  |- D) L" s
  16. 6 {" C% X* [7 |) S# l4 y% a# y
  17.   cJSON *root,*command_root;& b. Q  S. Z; K% _! o4 V: ]' b

  18. % s; e; w/ g3 b( b7 t
  19.   root =     cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)* ^4 F* I# ^; K' K: n
  20.     if(!root)  D! e3 @% E% i- Z( C' @( a
  21.             {
    ( {0 B5 [  F9 }: {3 K/ Y; J2 y
  22.                  //printf("get cJSON  faild !\n");/ I& p' c1 ?3 H
  23.                 cmdtype=NOCOMMAND;//如果没有,就直接返回0# r" K+ t* X) v+ E
  24.              }
    , Q; F) Z2 H. U0 z, k
  25.             else; Q- W6 I3 [0 A3 W- J
  26.                 {
    + G0 z. i  f2 A0 v$ _" F
  27.                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对& W2 L+ B( E/ P2 J0 g5 y
  28.                     if(!command_root)  t4 H$ W6 b' N- k2 h" p* y& L* l
  29.                         {
    3 M/ t* N4 @+ N! Z
  30.                                 //printf("No RobotCommand !\n");
    0 g) m( {/ ]! q3 G
  31. ; [9 E* R( E" c" l/ x
  32.                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对
    # m2 |8 Q( U( D- R2 D4 |3 L
  33.                                     if(!command_root)( F7 L' v% L% i, V' n
  34.                                     {
    2 n# F# q) w) l8 l$ }7 t& h
  35.                                          //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回0) M! ?4 J9 R- f' D: z) w
  36.                                              cmdtype=NOCOMMAND;//如果没有,就直接返回0
    3 z" F1 ]: h4 l% y/ F6 S
  37.                                     }% ~, {+ R; f: m! \+ u
  38.                                     else{
    " \) \  n  ^. N+ T7 ~% G9 U& ]8 ?& s
  39. " o1 S0 g6 x& \4 D- T; |* B
  40. / j! {4 N& X4 A# O$ r
  41.                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
    / r# }6 E7 j; c0 m+ k/ ~- |
  42.                                             if(!json_ack.ID)" f, s  z) r) j0 J" x5 C2 e
  43.                                                 {
    : `1 z4 R. X7 C6 I& F* I
  44.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回07 Q: O9 j% S2 m1 Q0 v, i# Y
  45.                                                 }* m6 V) l7 i* C2 y, O
  46.                                             else
    + _3 \+ h4 T* O/ O* ^
  47.                                                 {
    % W0 z. i1 `! y! H8 S1 ~
  48.                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);+ h0 D: m! `+ c: ]. M) `7 c4 Q
  49.                                                 }: e! w; z# q0 U5 a! E! P1 G+ w
  50.                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");  o! Z. q" l2 y
  51.                                             if(!json_ack.Time)4 }" i7 n8 ?- t7 l* T4 m- _
  52.                                                 {1 H7 N2 _. }/ J; R6 m& D
  53.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    3 S0 H- j& _8 W
  54.                                                 }" }0 q0 s6 i$ f3 A
  55.                                             else- [9 k2 V7 A" S& }2 Q, a# c. l, K
  56.                                                 {( Q" a0 j* R+ q( m
  57.                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);
    . C  o3 K" u( M6 y& k4 m2 X
  58.                                                 }
    6 w3 @: G8 I9 _+ f3 T* A/ P

  59. : ]- v+ f7 x% Q3 m% q
  60.                                                 cmdtype=HELLO_ACK;//如果没有,就直接返回0
    6 k  d" _6 U. L! @0 M+ q4 Y- w
  61.                                     }  l- x  |* J8 @: b4 h# ~" @( m
  62.                         }  ]) E% s& n" p
  63.                     else& K# Z0 X5 ?1 Y& e
  64.                         {7 g7 Z7 L4 y, ?1 F  v4 K
  65. 3 T  S6 u- c% c) Q$ d5 I5 E
  66.                             //运动命令
    " d' V/ P7 E) H! k5 Y, [/ a8 _
  67.                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");' Q% t4 J' e& _0 Z5 k" L' R
  68.                             if(!json_cmd.Command)/ m% m- a: w( v
  69.                                 {1 g8 i* W7 |* K+ ]
  70.                                     //printf("no Command!\n");
    7 W0 |* z6 B0 g2 V8 {
  71.                                         //cmdtype=NOCOMMAND;//如果没有,就直接返回0) [* R2 z$ O, Z7 d& V
  72.                                 }! P# z- g/ H: a! t( j' T3 R
  73.                             else1 `! \* {8 x. s$ B/ f3 g9 L5 h
  74.                                 {) ~) S! n3 m/ X, r, v+ y' \% C
  75.                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);9 r) a; x8 A5 A
  76.                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);
    + l9 k3 Q+ i' R  o' S, ^
  77.                                     //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议
    ) W9 j1 F5 ~7 s  r

  78. 7 t" f* E2 x" w5 v# T
  79.                                 }5 H/ H1 ]+ L8 [9 z
  80.                             //速度指令3 A) P# Z0 Z6 U1 E2 t' y, M
  81.                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");
    : F5 o* `9 h' x$ }
  82.                             if(!json_cmd.Speed)
    / A1 a. f; d3 |- j( [. t: R) k$ c
  83.                                 {
    , w& P+ A# \5 E" q3 z6 w$ j
  84.                                     //printf("no Speed!\n");
    8 ~3 T1 y! h: D. y, i) D4 j! J! h
  85. //                                    cmdtype=NOCOMMAND;//如果没有,就直接返回0+ i3 e4 V2 w2 W
  86.                                 }& D3 s  `' i2 b! i5 m5 m" s9 k
  87.                             else3 [3 b; j' P* X' z% n
  88.                                 {
    ' u( _- T" i/ o
  89.                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);. b9 M- M+ \% e4 V. j6 s
  90.                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;" H+ r/ _- K4 T' P. J6 V) L
  91.                                 }, Y; A* g7 |6 X4 c# n! o* L

  92. ) M3 y/ D% S: b- y# J9 W
  93.                                 //运行次数
    9 E# S; s# q. m% A# Z, h
  94.                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");
    ! |9 h3 @- Q3 D# y1 r+ H
  95.                             if(!json_cmd.RunCount)
    5 ~! p& h' H- |/ g- o5 r
  96.                                 {$ x  f- @+ u- u
  97.                                     //printf("no RunCount!\n");8 P7 R- x' A- x+ ^, w% H! n$ \
  98. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    ; B" G1 T# i1 ^3 i
  99.                                 }
    3 f& x1 P+ X) O: V7 R6 Q
  100.                             else
    ( z, Y* _) f+ B' M
  101.                                 {' O1 `" a6 y& I$ X
  102.                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);1 n' H. g4 B) r( Z# }
  103.                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;
    " i1 H% E! |9 c: W+ D1 ?: f# f
  104.                                 }
    8 ~. Z% Y5 a9 u2 F' T3 A" [
  105.                                 //开始位置2 d* T& a' |3 D) E
  106.                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");: r2 v9 }0 q3 I
  107.                             if(!json_cmd.StartPosition)
    : }# v5 a# x. S/ {: x1 k2 P
  108.                                 {
    0 n0 l+ [# N" ]
  109.                                     //printf("no StartPosition!\n");
    + ^/ R0 P2 {9 V& p' Y
  110. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0  D7 w) j$ [& E0 K# q% H
  111.                                 }0 Q2 i/ y  l. p
  112.                             else" m% p9 E1 A0 e
  113.                                 {
      f+ @* W1 y, W* Z% s6 Z8 P( M
  114.                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);
    & ~* @1 N- }$ g2 N5 C
  115.                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
    - f" a' P( g6 o# h4 G7 R
  116.                                 }# S0 ]2 [" k: p! A8 k& v2 e
  117.                                 //结束位置
    6 h/ ~+ r0 V% H( W9 V
  118.                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");2 O! @- ]" }* d. H
  119.                             if(!json_cmd.EndPosition)( h5 ]7 J$ v, K  h* k
  120.                                 {" S1 v0 d& `, v3 a8 P9 ~: |0 W
  121.                                     //printf("no EndPosition!\n");- x: y) @3 n4 w% `: @
  122. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0- ~* g! D) r% C2 V
  123.                                 }; D4 Q8 n$ H, [  Y3 D. t
  124.                             else
    5 O8 M) z1 [7 N; P* U
  125.                                 {
    4 F% F% W3 x+ l6 ?
  126.                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);( Q" `! |1 v% G8 M. A/ a% @( |
  127.                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
    : L( T6 C' W% k5 h
  128.                                 }
    % v7 G9 a/ t8 R% T( ]
  129.                                 //目标位置TargetPosition
    . P& y6 n) @2 s5 |) [8 q: o' F
  130.                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");
    ' m, w. D, R4 a2 ~; L
  131.                             if(!json_cmd.TargetPosition)9 @! m* F% Q" K$ C
  132.                                 {
    % M0 z" m9 b* y  m% J5 |6 s# Y
  133.                                     //printf("no TargetPosition!\n");
    ( V& y4 J; i5 J- s$ B
  134. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0& A* J2 Y0 E* |
  135.                                 }
    8 u3 {7 K( H" V1 ]; i- q! n
  136.                             else! f* P) d2 i) w4 h" H' {
  137.                                 {
    ( m5 S" \: G' D/ t6 p) F+ e
  138.                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);- o# f  f+ \, R% @! t0 Y1 O
  139.                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
    ; b% J) U2 B) h1 f6 h" f3 c9 |
  140.                                 }
    " {, h! Y, E) U! K) J

  141. ( d4 r% ^& c! c8 B, H0 h: m0 p
  142.                                 //*工作模式WorkMode;
    1 [$ Q: Z+ i3 W5 c
  143.                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");
    ) k& z# ~) a: C* k
  144.                                 if(!json_cmd.WorkMode)6 B  F2 f' c0 L
  145.                                 {
    5 J0 B6 X) s# A- ~0 {# N
  146.                                     //printf("no WorkMode!\n");
    7 j# I+ @4 ]* K1 k) P
  147. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    $ A2 J- @) D' v: \& z6 k  y
  148.                                 }8 K: V3 @/ Y/ Y) K' i5 s
  149.                             else
    $ _6 [" c' D0 z  @
  150.                                 {
    # L$ R: m& d; I7 Y9 D$ c
  151.                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);" E/ q& A' W3 U: X
  152.                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);* K( O$ ^) |4 ], @7 r
  153.                                 }
    - [7 g5 f" S) z
  154.                                 //step1 P" p' }0 F* f( a/ a& N, F
  155.                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");: D: M# q( F" E, b
  156.                                 if(!json_cmd.Step)
    $ v/ ?* l0 e$ I6 r- G  N
  157.                                 {
    4 l' M" j. j+ L$ c
  158.                                     //printf("no Step!\n");2 S/ Q# ^- x: E
  159. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回02 E. b0 z# M  T) ~" B
  160.                                 }+ W' G- l& O$ E% h, Y
  161.                             else
    . g' B% E( N( l9 x6 W& F
  162.                                 {
    * N  O# w- Q3 {. e
  163.                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
    ) D( g+ R5 I/ b! @' A
  164.                                             Cmd_From_Server.Step=json_cmd.Step->valueint;  @/ y8 g; t: L2 V% ]/ r0 ?
  165.                                 }
    7 N$ \: X' _3 j$ `

  166. 2 Y0 N, Y6 K8 Q6 `. \- Q
  167. ' E: |% d8 @9 r2 c* v/ Y% E
  168.                                 cmdtype= COMMAND;1 e$ o  D" S2 J* r( r- c
  169. , Z, D+ b) S4 V, L4 h" g; l
  170.                         }$ Y: n( y- w7 D
  171.              }3 u1 g1 b" t8 W7 I" u! [" A$ b8 I; h

  172. , M  x4 ]8 D4 K
  173. cJSON_Delete(root);
      X4 X# r* i% y" Q# y3 i4 f
  174. ! X. w& o& u) o# E
  175. return cmdtype;7 ^& S. O! O$ E; V; \
  176. }
复制代码
* p4 k* T: L: i$ P: D0 `) p
, t0 I9 |1 U+ O: ^9 o( P
收藏 评论0 发布时间:2022-1-28 19:01

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版