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

【经验分享】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字符串
    " l- I; k# X* \  C

  2. & h& C+ S1 q. s* \; L
  3. {* k8 c7 V: Y4 }% P! }0 V  b: J

  4. ) Z! F/ T* t& r" Z: e
  5.       char *result;0 V  M3 z# [, T; d) T
  6. * N3 |5 U, `7 E+ k% P" ?
  7.       cJSON *root,*subroot;//新建两个cJSON的对象指针
    # S. n3 N* T" j& |& p
  8. 9 E1 X, r; i7 P
  9.       root=cJSON_CreateObject();//创建一个机器人状态的JSON对象
    ; ?  ^$ s' c  D8 G! m: F
  10. : z; K4 F! u9 s& I  V
  11.       subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象
    5 Y2 B  E% C# X) {
  12. 7 I9 u! C8 I$ G* X
  13.       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。
    ; E6 X6 {" `! l1 j, W# Z

  14. 8 M/ t" s7 [6 ~# m' ?$ f( T& s( S; ~" n
  15.       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);
    7 R7 `) P& y9 J' E; N/ U
  16. 4 U  Q3 q! g2 E7 {' m  a; g0 x9 k
  17. //同上9 u$ [2 W% j: g0 O& `8 T

  18. 6 z& H5 u$ @2 r0 D3 M8 g! K0 u
  19.   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);5 V! R" ~9 M0 Q

  20. - Y: h& t. I$ t
  21. //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型" j2 H: D' u) u( m& |0 r" t5 O
  22. 1 A' ]$ h8 K; J( [- y* Y; n. S
  23.       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);
    % j3 b/ a: k* G6 z+ @

  24. & N; u# A4 r3 \: F' [5 j$ |6 J
  25.       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);& c1 x: t+ ~) h( M! y& n+ s# U
  26. ) [+ Q5 Z( w7 l8 R$ h  J3 h
  27.       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);- x4 t2 u4 W& {7 `* ^

  28. ' I- Z8 H+ K: ~7 N3 i- _
  29.      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);3 U% Q$ F/ e+ T& {8 m" T

  30. . J9 f1 J. L8 l, w, H
  31.       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);$ v4 A9 c# ]) F- b3 D4 G

  32. ; l- W, J3 ~( y; d# \
  33.       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);) B' h5 F, t. p+ P% c" {/ y9 _

  34. ; q, k$ g2 k$ I7 }, ~
  35. cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);  G) @% j. |, q; B3 j8 m3 R

  36. 1 T+ H9 v0 U" O- J  g  H
  37. cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);5 E/ Z3 u0 T/ D% s+ }# F
  38. $ k: T$ j) C+ a  H4 O
  39.    cJSON_AddItemToObject(root, "RobotStatus", subroot);8 ]9 e0 O" h, M$ l% ?

  40. # n& Q( s/ G/ C( O
  41.       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间. d0 v0 G, c& R+ O/ R$ v# P

  42. . [6 `/ J4 w8 A% ~
  43.       strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量
    ! I+ E: S% e4 a  T
  44. ' r, r. ^/ L" P( l9 a( F" {
  45.       cJSON_Delete(root);//最后将root根节点删除
    / e* S! i$ @/ w$ e$ ?+ @

  46. 9 E) B" F+ H6 e! g  B# l: O
  47.       myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃- W8 k, r1 E( V3 E

  48. ' Z5 d' }: l; a% N; o
  49.       return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。
    + P: p. Q3 R) v+ i, N5 K3 ~& U

  50. 8 C$ s& [( o  V: r% {1 A, ^
  51. }
复制代码
注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。
  1. #include "malloc.h"
    . C( i" h+ F+ y( z# J! A

  2. 7 o" n5 `/ T0 _" |% L
  3. //内存池(4字节对齐)
    ( q; F& {# V+ Z* P
  4. __align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池' ]) F" M5 {8 n) l
  5. //内存管理表
    # z3 e, @0 \/ ~4 G* E, ?
  6. u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP7 @& S, z' L0 m8 Q# S
  7. //内存管理参数) N$ ?/ f: ~0 ^% x* p, n* q4 O
  8. const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小
    5 l- q1 A$ n* Q& L- }
  9. const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小9 J9 J0 |& w: ?0 F) ?7 G, D/ P
  10. const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小$ c9 u( p" |' I5 U. }! d. J9 H

  11. . Q( ]  F  m; h# z1 S

  12. * E' u; @  R: S' _9 B4 B& N0 d
  13. //内存管理控制器
    7 e- g1 s, g+ E% [2 d
  14. struct _m_mallco_dev mallco_dev=
    - I) V* m# F1 N8 w$ x
  15. {
    ; d7 }% H# z6 k9 @3 V( Z& J
  16.     mem_init,                //内存初始化1 N1 ^+ n* R& \/ \9 q6 P
  17.     mem_perused,      //内存使用率! G7 P# A( N4 ~! E, Q6 y1 `
  18.     membase,            //内存池
    # c1 ~8 I$ }- l1 l7 A
  19.     memmapbase,     //内存管理状态表' y5 ^0 H& h3 X2 c) s* Y6 L% X
  20.     0,                        //内存管理未就绪
    % u9 G8 U" a7 R
  21. };$ y! G) k. T9 u4 v  |4 Q7 ~- z
  22. ; s5 c; g% T. T, b0 L
  23. //复制内存
    ! a5 h* V6 d( v  {2 J
  24. //*des:目的地址
    7 G$ r& ?4 I  ?. h3 J
  25. //*src:源地址
    3 b- E& T. n9 q" m1 g
  26. //n:需要复制的内存长度(字节为单位)
    / n2 N) p+ p+ C
  27. void mymemcpy(void *des,void *src,u32 n)
    6 F9 V, e- x3 r
  28. {9 H/ x! c* W( f  p" Z& d7 \
  29.   u8 *xdes=des;
    * i4 n% D' ]- ~3 @
  30.     u8 *xsrc=src;- N4 \& ^0 t* b9 |( G% A( q2 `: T
  31.   while(n--)*xdes++=*xsrc++;
    ; D) J$ J: q9 M1 K0 ]
  32. }" v! D; E* X; b+ V
  33. ; U2 V& }# Z, A$ y
  34. //设置内存
    ' A  Q( {3 u8 n: c. v3 H# n
  35. //*s:内存首地址8 ^$ }: e' j4 Y+ _1 t! ]9 R# L
  36. //c :要设置的值) E8 e- C7 R& Y/ c
  37. //count:需要设置的内存大小(字节为单位)
    * l# ~' H0 f; ^- C) T7 J
  38. void mymemset(void *s,u8 c,u32 count)" ?0 M6 U: ^3 p8 \
  39. {$ \! N" _" s8 U* K& Y! [
  40.     u8 *xs = s;' z' J3 p* Y! `- q4 E( y
  41.     while(count--)*xs++=c;
    ( C0 I5 F. x0 p* {* R
  42. }
    . K4 [7 b  }; B6 [( @; Q% y& V, ]5 r
  43. " \6 C+ U- `/ |$ o( f" J8 t$ B
  44. //内存管理初始化
    + r6 H. E, R2 z# o& x0 q
  45. //memx:所属内存块
    * y! t) a- q: S* u  M
  46. void mem_init(void)
    * y& v. B) k- E0 x
  47. {
      J% H: O6 c; [8 P
  48.   mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零( A9 E$ t" `5 L7 ?3 g' `$ w9 `
  49.     mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零- v. b) p! X: _% ?; y( r) f0 E
  50.     mallco_dev.memrdy=1;                                //内存管理初始化OK" E2 L% ~( \+ m) h! S0 H
  51. }
      ^# U. K$ t8 F
  52. 6 g0 k. [/ q( h( u9 {
  53. //获取内存使用率! w& ]( ^9 k6 U" }
  54. //memx:所属内存块! h7 b$ i( v4 M5 V' E: ?7 i
  55. //返回值:使用率(0~100)! M' Y( U. z1 ?) X  A( V
  56. u8 mem_perused(void)- r. v8 l7 n8 P7 f; T! @6 g5 n4 o
  57. {7 N& E3 Z& I+ w9 o& j
  58.     u32 used=0;
    7 s! l4 u2 T2 o8 b( |/ ]
  59.     u32 i;. t) C  K" |# o
  60.     for(i=0;i<memtblsize;i++), }* r2 l9 U6 _* F
  61.     {
    9 w) A" d! ]$ P( M, O* Z( ?
  62.         if(mallco_dev.memmap[i])used++;' v( ]0 M$ [0 P4 H
  63.     }7 W$ @  ?9 b- F) c/ ~5 u! [9 G. A+ j) n* G
  64.     return (used*100)/(memtblsize);
    & v+ a0 v2 {: D- I/ u
  65. }
    " S7 x, P. Y: p, \

  66. + a, }( R3 n7 C6 C3 d
  67. //内存分配(内部调用)
    6 b, g3 q% i6 \& q
  68. //memx:所属内存块% C0 D3 s# j/ t4 j& l" ]
  69. //size:要分配的内存大小(字节)) G  N; ^0 y. H# A
  70. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址& s! A% U6 x7 f' ?0 f8 n8 Z
  71. u32 mem_malloc(u32 size)
    $ u+ N8 w' H% Y7 c! p1 u# E
  72. {
    - T& T' v/ ?+ X0 n7 J
  73.     signed long offset=0;
    . R4 I5 w. e' {% ~3 ~
  74.     u16 nmemb;    //需要的内存块数
    ( s/ f8 r4 f- D& B; M
  75.     u16 cmemb=0;//连续空内存块数8 F# N( W6 V/ }' @  t6 D2 l/ y
  76.     u32 i;# x2 m- h5 J3 H
  77.     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化- L) r3 b7 z6 }2 ^2 Z0 x
  78.     if(size==0)return 0XFFFFFFFF;//不需要分配8 F  ?9 }1 L; ~5 R# d0 A& x# g

  79. + K8 @) T/ K+ g: w0 w) `. F2 Z3 L2 m
  80.     nmemb=size/memblksize;      //获取需要分配的连续内存块数# \7 ]: ^# y9 |3 G% o+ p+ z3 |
  81.     if(size%memblksize)nmemb++;
    * [+ d6 a4 L2 }) h: z
  82.     for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区( ?& X% I5 D* s$ A+ v% D% C& z% ]
  83.     {
    2 @3 U- C5 w* @
  84.         if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加
    ! ~; f+ j2 @: D2 Y% Y% j
  85.         else cmemb=0;                                //连续内存块清零
    " B4 f& d  q- g+ C2 K! B4 p5 Z
  86.         if(cmemb==nmemb)                            //找到了连续nmemb个空内存块' i0 F$ @3 ^5 q. ?; \, s0 B
  87.         {
    3 F! Q1 ]# }' {( K0 W) A/ k
  88.             for(i=0;i<nmemb;i++)                      //标注内存块非空
    - I9 g0 K: l0 [* b! I) f& P9 G1 C
  89.             {- o5 D/ f8 b9 b6 ]  ]7 m
  90.                 mallco_dev.memmap[offset+i]=nmemb;
    * V# G8 |' i0 M, T; u8 W7 w2 a$ C
  91.             }. }) x1 p) |; C$ A: L5 ]( Y
  92.             return (offset*memblksize);//返回偏移地址
    ! a! K3 b- u! ~+ L: ~
  93.         }8 R) h# n( T: f: U! J3 x
  94.     }
      h( j3 z! D, L1 b1 x
  95.     return 0XFFFFFFFF;//未找到符合分配条件的内存块, W" n8 {# d( s
  96. }' _! \; A5 e. D4 ?

  97. 0 y0 l* W0 s1 Y3 S% u! j
  98. //释放内存(内部调用)
    % I+ w  \4 e* ]8 a  U
  99. //memx:所属内存块3 ?1 G5 `5 B/ O! s' S
  100. //offset:内存地址偏移4 q: I7 R  k3 S$ V
  101. //返回值:0,释放成功;1,释放失败;
    - w( L/ k3 _0 i, C& m& r" e$ X
  102. u8 mem_free(u32 offset)5 d, |* ^0 \1 W
  103. {& e0 Z  Q9 g5 k- D  d2 |, S
  104.     int i;, I  i. u1 v4 g3 [* @7 t0 h/ a
  105.     if(!mallco_dev.memrdy)//未初始化,先执行初始化! L" g& l; l% e5 K/ j( c
  106.     {4 z3 }, J. h4 b& Z8 r
  107.         mallco_dev.init();
    5 @; }6 M+ u) m: C6 x, m# i
  108.         return 1;//未初始化" u( b1 i& N1 i
  109.     }. ?; ?5 U8 Y% q+ q7 B, p
  110.     if(offset<memsize)//偏移在内存池内.! p8 O- ?; a; [6 [: d) |
  111.     {: K: m, w8 a7 y4 q- X% E
  112.         int index=offset/memblksize;            //偏移所在内存块号码! i: s% g7 O( P$ [
  113.         int nmemb=mallco_dev.memmap[index];    //内存块数量: H6 `- j- E) c3 ]1 q, Z% M6 k" j: V
  114.         for(i=0;i<nmemb;i++)                          //内存块清零2 W2 H/ ?& z5 Q2 C( e3 L' Y
  115.         {8 ?' v# t/ e" z
  116.             mallco_dev.memmap[index+i]=0;$ w$ g+ `1 ?+ `! B
  117.         }! C0 m; ~; A) b9 X; k/ t2 h2 s
  118.         return 0;) k% k( t. S$ K
  119.     }else return 2;//偏移超区了., t( @7 ^, L* g/ h
  120. }: s5 d* l: z) A+ U

  121.   z# ]; Y1 [" Z& ?/ ~  ]8 A0 \
  122. //释放内存(外部调用)
    & w) D4 I. {% U, Y  C5 m' [8 g
  123. //memx:所属内存块0 A% f$ ^0 J, c4 C, X9 m( R8 m
  124. //ptr:内存首地址
    7 j" Y" S4 c, A, W2 L) h; K
  125. void myfree(void *ptr)% i0 \$ {- Z' N. R, `2 K: K7 B
  126. {  ^/ v4 w. }* K& t/ w, c
  127.     u32 offset;
    . T' r2 U) @% C# R
  128.     if(ptr==NULL)return;//地址为0.
    5 l2 l9 ^7 c# Z5 B3 i2 f
  129.      offset=(u32)ptr-(u32)mallco_dev.membase;
    : d% }2 {* g& E0 W/ w& x* ^' r# n
  130.     mem_free(offset);//释放内存/ Y) l- A2 S, c, _: x0 N
  131. }
    / T2 R9 `5 i5 t9 x

  132. - @" T  q1 c2 u: W
  133. //分配内存(外部调用)
    - k! W& I* ?1 H' P4 X$ }/ C
  134. //memx:所属内存块
    # q, D& n% T: |5 z& W, p' V
  135. //size:内存大小(字节)2 j: ?9 v" S2 ]) ?- I/ @* S/ {
  136. //返回值:分配到的内存首地址.
    2 `8 |) F' g$ t
  137. void *mymalloc(u32 size)
    + n# [# O$ }, ^' v$ `, A. c
  138. {2 r- S6 e$ M+ b( b- Y
  139.     u32 offset;
    5 ^' v/ L; [# ~% j  ]/ G3 S
  140.     offset=mem_malloc(size);* J3 a( {) r: B/ ?
  141.     if(offset==0XFFFFFFFF)return NULL;& z, b9 e: V  V2 u" U  V
  142.     else return (void*)((u32)mallco_dev.membase+offset);3 D4 T1 \! F& H, N
  143. }8 }# B+ v- S( G# `# O" |& n
  144. + R  G5 f  t, O2 _6 O: Q$ {
  145. //重新分配内存(外部调用)
    1 K$ U8 n+ q% X! l
  146. //memx:所属内存块
    3 N. T; n2 Z/ b3 I
  147. //*ptr:旧内存首地址
    + H. a+ w* R( ~% I9 Q8 ]
  148. //size:要分配的内存大小(字节)
    1 W3 v1 ]& O( }
  149. //返回值:新分配到的内存首地址.6 O/ R3 n# `% m) @9 d; ~  N
  150. void *myrealloc(void *ptr,u32 size)
    . f5 |2 M% x; p, [3 e0 d
  151. {9 ~! N- q3 D9 u7 Z) n2 V: ]- z
  152.     u32 offset;
    ( K; p. L  M+ M- W: }  D  |
  153.     offset=mem_malloc(size);+ Y3 s# y2 s/ l6 @5 Y
  154.     if(offset==0XFFFFFFFF)return NULL;6 |& O2 I) d3 @) e) s# A' A, h2 w
  155.     else
    9 b6 B: p8 m/ y3 M5 `
  156.     {7 u( d; u* Q: [) a8 k8 C
  157.         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存
    9 f4 W/ G; ]0 ], N
  158.         myfree(ptr);                                                        //释放旧内存( a+ U+ s1 U! b! j6 T" i
  159.         return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址
    9 d9 r( k/ c. X) \5 A8 D, \
  160.     }
    / i( ?6 G* X  I" h% w
  161. }
复制代码
malloc.h内容如下:
  1. #ifndef __MALLOC_H
    # l0 R( n6 l3 d9 h
  2. #define __MALLOC_H' v0 s: b( s, d7 g9 ?
  3. #include "stm32f10x.h"
    + g% u# `8 {9 H

  4. , O4 E4 T, w! @2 F. m
  5. #ifndef NULL
    1 r8 I. }1 u- I9 J; d
  6. #define NULL 0& H( R9 h+ {. ^0 i
  7. #endif
    / p- ]" j5 J8 Q0 G, ^
  8. % C8 v0 ^3 f8 z& `  k
  9. #define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节5 Q& J* _3 L- a& ~- j
  10. #define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K8 C& c- g$ O: u1 C, h+ F4 p
  11. #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
    ; t. y  D* S# D# Y% `

  12. / q+ F4 p( L1 p9 W4 u! c% j2 R
  13. //内存管理控制器! l5 o, n: t) x6 B3 G/ I  ?: A) z9 P
  14. struct _m_mallco_dev( u+ j7 |1 O! ?3 }  D8 q; d
  15. {* k% |$ T6 b5 i: W
  16.     void (*init)(void);                    //初始化
    4 R$ z3 ?6 a, o( p; I; \' B
  17.     u8   (*perused)(void);                      //内存使用率
    ) @5 C" f/ l( E' E
  18.     u8       *membase;                    //内存池
    , s1 |% T* i/ ]! n$ R0 P" w
  19.     u16   *memmap;                     //内存管理状态表1 w  I1 W% z) u7 w/ m' o) c, t  ^" G
  20.     u8     memrdy;                         //内存管理是否就绪
    , O1 a* e9 c5 h, Q4 |: t9 C* W) }
  21. };7 ~/ o+ ?  T+ u' C" n) e* f- W" Y
  22. & t9 L% {/ S$ U. O
  23. extern struct _m_mallco_dev mallco_dev;     //在mallco.c里面定义
    . t& n3 F1 @# W6 |

  24. & l3 C) q; f& ~$ Z; h6 q' Z
  25. void mymemset(void *s,u8 c,u32 count);     //设置内存) w/ l; p4 Q. L: a1 ]
  26. void mymemcpy(void *des,void *src,u32 n);//复制内存
    * K# R4 B$ E( h- f6 w+ V

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

  3. ) W( |) P4 Z3 A( l! x
  4.   Permission is hereby granted, free of charge, to any person obtaining a copy
    / K8 Z- n/ c9 I, j; L& z; H0 T( g
  5.   of this software and associated documentation files (the "Software"), to deal/ r! I$ E) Z. |$ w) `
  6.   in the Software without restriction, including without limitation the rights2 p) z' ^( T* b5 |( n
  7.   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell/ n. z$ ], i# |( J# v; _0 n& p( z
  8.   copies of the Software, and to permit persons to whom the Software is# r5 ]( m+ u4 I" [  K
  9.   furnished to do so, subject to the following conditions:
    % h" i* v$ J# m5 L  e
  10. $ v( m# x- L# v# y; `) q
  11.   The above copyright notice and this permission notice shall be included in- f' b1 ^: v0 B* v, s  a
  12.   all copies or substantial portions of the Software.( j! A1 G) B0 E2 J, W
  13. / l& C# f" A0 |: K8 V, {
  14.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR6 k& v( z- \4 i1 s/ U. G# Y' q
  15.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY," _" D4 C/ G4 f: z/ V
  16.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    4 M) j' c. |# {
  17.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    ! j1 C, ~: J: w' p; i( {# t0 A3 F0 j6 f
  18.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,; C( I" a2 I; R6 a5 p+ Q
  19.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN, ]& ?7 n% U1 l. p+ H
  20.   THE SOFTWARE., D  Y3 `- t2 M+ K5 ^) W  {9 ~
  21. */' o- u: r" O* e: Y( B

  22. : ^( P6 o# L* O+ @  P# g
  23. #ifndef cJSON__h2 ?/ V2 a0 u4 U
  24. #define cJSON__h
    - U1 q# G0 p% ~3 z
  25. $ G3 i* v& K& w, T
  26. #include <stddef.h>
    2 a- p% }% L9 F, m) V  K
  27. " r9 R0 _9 g& B9 v' R' t
  28. #ifdef __cplusplus. h8 G# ~# v: p9 d0 J9 p
  29. extern "C"
    & Q+ \, u7 N% e7 Q/ f1 C
  30. {$ {  n6 b0 i; s0 E; ]' \, N$ A
  31. #endif
    , H& X+ E; M7 H/ F! }  Z% C, F+ l

  32. 3 h- t, C! D3 I
  33. /* cJSON Types: */
    5 ?. B* g4 I/ U# V+ A3 k; ~: H
  34. #define cJSON_False 0. u9 y3 ?& d: m0 d# v; U5 ~' r6 w
  35. #define cJSON_True 19 T! E: P* A9 N- i0 x
  36. #define cJSON_NULL 2
    " Q4 e0 \# p3 a
  37. #define cJSON_Number 3
    & L- t1 W, R/ \4 T
  38. #define cJSON_String 4& X- A# n5 r; i: M' x
  39. #define cJSON_Array 5
    + v6 X) L( n% h: {! H8 L5 ~" Y$ n
  40. #define cJSON_Object 6) [% O  |' l3 C1 [; H

  41. 5 H/ ^, L  e4 q$ }  b& G6 I, b
  42. #define cJSON_IsReference 256
    - E. G9 o0 ^+ K" s- J+ _& y3 ?

  43. ' ]- M# L+ `  M4 S( i
  44. /* The cJSON structure: */
    / b3 h3 F: f. l7 u+ l. s
  45. typedef struct cJSON {5 |/ q* E/ Y7 W* z  W
  46.     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */3 X* V8 j, }7 |- `& C; M
  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. */; Y) c% T& P6 |# w

  48. + Y6 s: K* c3 g' p; a+ j
  49.     int type;                    /* The type of the item, as above. */! ^' Q8 L0 D/ \8 s+ s
  50. , h& B! W1 e, _6 Y5 {$ G2 {
  51.     char *valuestring;            /* The item's string, if type==cJSON_String */$ G$ [) T" W! d: v- B. S: z
  52.     int valueint;                /* The item's number, if type==cJSON_Number */
    0 m3 F6 g# T; _4 u- a' J
  53.     double valuedouble;            /* The item's number, if type==cJSON_Number */
    : K" G3 N+ a  e% [- H0 ~; W- E6 E

  54. , `% y% W* k; W& V& v1 D6 z
  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. */
    . R3 f6 g. {1 w9 M- Z0 q1 J
  56. } cJSON;
    8 M; M! V& T/ e
  57. 7 V% a8 w( [1 ]- }; _
  58. - j+ w2 @4 k' C7 H0 u5 u  U

  59. 4 y2 B3 `4 x! I, \( U& q' W
  60. typedef struct cJSON_Hooks {
    7 o4 b' e7 U- v4 f2 z
  61.       void *(*malloc_fn)(size_t sz);+ V9 W$ c1 V. V; Z8 v
  62.       void (*free_fn)(void *ptr);- d6 y* U* E! `5 l# ~
  63. } cJSON_Hooks;
    + [) `: R) f3 @8 k/ {# V5 D; W6 A/ b

  64. / e, `7 d' D% o5 S5 }& p; O
  65. /* Supply malloc, realloc and free functions to cJSON */
    ' q3 G: a9 q/ ^1 F
  66. extern void cJSON_InitHooks(cJSON_Hooks* hooks);
    8 [5 A1 v! L2 w

  67. * A  V- O6 B9 D. r

  68. ! u: c6 @. F8 G" |
  69. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */: a" O( x3 c6 ^- @3 l" G* `* o
  70. extern cJSON *cJSON_Parse(const char *value);
    & g6 W; g: ]( K* v/ U
  71. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
      {3 W2 U) f+ X( P
  72. extern char  *cJSON_Print(cJSON *item);
    ! f' k. K* m6 y# H
  73. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
    ) n; c" H+ _- [* O; e, m$ N4 B) J! Z
  74. extern char  *cJSON_PrintUnformatted(cJSON *item);$ z" V' s- e/ j6 j+ r8 h
  75. /* Delete a cJSON entity and all subentities. */4 L  ~* o8 {1 `' t$ u8 [
  76. extern void   cJSON_Delete(cJSON *c);
    ' K! @' Y" C! h( I2 r( U6 }1 a% z

  77. 9 u! w4 u$ E: L7 W, I+ R! p* h6 x
  78. /* Returns the number of items in an array (or object). */
    , u0 l- B3 Z5 N5 U* F: L8 ~. H$ Y+ S
  79. extern int      cJSON_GetArraySize(cJSON *array);
    / c9 D1 g7 [6 U& j% @- q! {
  80. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */* ^+ H* [8 K8 R& ]. i
  81. extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);- w. N/ d+ F: L3 t% r7 T
  82. /* Get item "string" from object. Case insensitive. */
    . Q- R0 T# K8 |8 S, Q
  83. extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    4 z. A/ O. e  V; Y/ ?3 F

  84. 1 E# S$ q  k* L' h2 B% b9 B
  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. */
    ( {) S+ L+ y. z- |, T" S
  86. extern const char *cJSON_GetErrorPtr(void);9 s: h, W3 H% a0 w$ a& v: O7 ~9 s

  87. ; }. L1 X" q1 N! P$ M, V( w/ K) t
  88. /* These calls create a cJSON item of the appropriate type. */
    ' F" J, c' W/ W& b
  89. extern cJSON *cJSON_CreateNull(void);& W5 g. U7 K. R. I& Z
  90. extern cJSON *cJSON_CreateTrue(void);8 q* x- ~: j1 e) r* U% C# J$ p  Q
  91. extern cJSON *cJSON_CreateFalse(void);
    - J$ P, k2 B1 _! w* J" o
  92. extern cJSON *cJSON_CreateBool(int b);
    4 ?% Q& e9 u! v5 ^
  93. extern cJSON *cJSON_CreateNumber(double num);
    ! e! v6 R2 [  a, h0 {; f
  94. extern cJSON *cJSON_CreateString(const char *string);# d# `. @" q- }% u7 Y8 ~
  95. extern cJSON *cJSON_CreateArray(void);
    ; G1 {8 v) }; h: K+ i0 D4 A+ E2 L
  96. extern cJSON *cJSON_CreateObject(void);+ j3 Q, T0 D6 w$ K" V5 G3 h
  97. 9 d! _3 f' v% x- M
  98. /* These utilities create an Array of count items. *// e: ]5 O+ S/ Y. `9 E& B
  99. extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);2 a5 y( u6 `. A
  100. extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);  N0 r" X0 l0 P7 O3 @
  101. extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
    4 Z9 t3 M: K! K/ d9 z+ D* `
  102. extern cJSON *cJSON_CreateStringArray(const char **strings,int count);" S7 r7 {4 J* m% q; f% C0 i
  103. ; C. d+ t. O9 ^$ R% K
  104. /* Append item to the specified array/object. */
    2 {: J& W: H" @; \; H
  105. extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
    ( k5 {' e# |- o% H* J
  106. extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
    # U8 N% P9 h+ g$ F0 v! F$ U
  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. */" i, L8 q( Q7 J. v% ^9 V
  108. extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    / `, m/ t& Q4 k, G! L) ]
  109. extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
    1 N3 G* t# L- J. J
  110. " u) b# ^+ q" S* V
  111. /* Remove/Detatch items from Arrays/Objects. */
    2 Z; x1 T  Z6 j, @. @* n( G: c( y
  112. extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
    " P7 Y. g* G$ |+ j& I$ ~
  113. extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);. o* ~7 U/ \2 w9 \0 z9 ?6 `! L
  114. extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);9 P# w& K3 A8 z# n) J- f4 u- H
  115. extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
    % m9 ?$ U7 g9 T! M5 m- k

  116.   _! D  y1 \+ x3 p2 O
  117. /* Update array items. */
    ) n7 c4 T" ?3 a. f% e, v4 i
  118. extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);: b8 a/ P" z. c6 p* a
  119. extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
    2 r$ k/ a# @; K" `6 M) I

  120. 5 X) @/ _, y  {8 D. {0 {
  121. /* Duplicate a cJSON item */4 R+ G7 ^* L* }2 ^
  122. extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
    ; L) p8 G# Z9 t0 t
  123. /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will9 X0 n2 z* U0 C: P5 q) D
  124. need to be released. With recurse!=0, it will duplicate any children connected to the item.
    # H2 A- x9 l3 {5 J# {
  125. The item->next and ->prev pointers are always zero on return from Duplicate. */
    3 H$ W1 x/ W# D  n& I
  126. ( `: H8 m8 H; |* r" P! m: d
  127. /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */9 C# L; ]  {; W6 B: A' r9 `% N* r
  128. extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
    4 O$ _/ l0 @6 W! c# u9 X4 B
  129. 7 b- w7 ^; r8 E# ]7 \- `1 z/ Q
  130. extern void cJSON_Minify(char *json);* \/ e& W# i% r. r4 N2 R

  131. + l9 D  X' G' S( Z
  132. /* Macros for creating things quickly. */8 b6 \8 C: O& Y! ]. o: t/ v1 j6 g. k( g* C
  133. #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())
    + ^4 _4 [& o' l  {% V# y) q
  134. #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
    ! y% R+ `6 F7 f, ^% h4 i- z
  135. #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())3 |# Q0 U; T# |6 @4 J* L* G; W
  136. #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
    ! s  ?% \) l: b' U9 N& d! q" m, u
  137. #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))/ p  C0 v9 b3 v- G, ^) F/ o8 e% S
  138. #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
    . y0 C, Z+ Q; g$ h; Y4 _  c

  139. 6 D( X$ k* i2 M, S
  140. /* When assigning an integer value, it needs to be propagated to valuedouble too. */- S; D/ T& k1 Z7 x
  141. #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
    ( A$ ~  B! e# c6 c- o# r1 _$ h/ E

  142. 2 |1 P' n* d* _" M0 Z$ W, `
  143. #ifdef __cplusplus6 P, b3 T- a1 }5 J$ T! r* W, s8 W
  144. }% M+ f! E+ t. t2 {' V
  145. #endif
    + x/ G* \& }2 U$ o+ n. |+ ?
  146. 0 o6 o" s9 p" H' h! ]6 c: }' K
  147. #endif
复制代码
下面是JSON数据的解析部分,简单说来就是对号入座。
  1. /**************************************************************************8 z4 J. y  {: Z" V7 x! p. o8 U
  2. 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令
    & i- I0 ~) I% U" ~+ t
  3. 入口参数:JSON格式的字符串,
    8 b3 \1 a3 Y4 w
  4. 返回  值:指令类型- d0 s. _5 v2 |- |( l
  5. 注    意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数9 X0 ?9 U/ _* P! @( x) U
  6. **************************************************************************/
    ' |* _* A! N. C1 l6 T1 o( y
  7. CommandType GetCommandFromServer(char * JsonDataFromSocket)" Q& h3 n2 m, P. C) u$ e# c
  8. {- f4 T& {; ]5 U3 P& m" p

  9. & w+ X8 d0 y7 e
  10. //  ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替
    ) L2 d: ]+ e7 Y1 o* r

  11. 3 l3 W& s( _, M* J- r1 N7 Z  _
  12. //    Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替
    , m) \" `* d' C5 Q5 V3 ^1 e+ C  ?
  13.     CommandType cmdtype;
    $ A+ {" a9 h% f
  14.   RobotJSON_CMD_TypeDef json_cmd;( x0 M+ v0 F' ^2 Q
  15.     HelloJSON_Ack_TypeDef json_ack;  P* [7 G. V2 b  @( L

  16. 8 L9 ~# X$ S- s0 m" M
  17.   cJSON *root,*command_root;
    ) `* B0 T4 D" X: O. ~) k
  18. 4 a4 v7 S1 q2 [' c
  19.   root =     cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)* E) t* q* U7 A
  20.     if(!root)# w0 S+ o0 U& ?8 r
  21.             {' D. p6 _; x/ ?9 F
  22.                  //printf("get cJSON  faild !\n");2 v# [) l$ O8 N# |& G  G) N
  23.                 cmdtype=NOCOMMAND;//如果没有,就直接返回0* R) S! s7 _- q/ ~) w' h8 C8 L
  24.              }
    9 q2 _9 O4 G5 v8 B. p; ~
  25.             else
    , R* a% ?% W/ p" T  k# l: F+ X7 r: b& f
  26.                 {( |) T( T) s1 O9 c
  27.                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对+ w& e; J7 h  G$ K
  28.                     if(!command_root)
    0 p' n" x  |& o/ f' d
  29.                         {
      i, }& A& ~% j3 R
  30.                                 //printf("No RobotCommand !\n");( o0 r5 z- `/ B4 Q
  31. " t* V. R; z* H2 d1 w) G
  32.                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对1 X4 \  g" j/ I4 E4 u( c
  33.                                     if(!command_root)
    6 l; K3 B' M1 L# o% H+ o% @- v
  34.                                     {
    0 \! R9 E( E# t
  35.                                          //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回0, ?2 r- Y* G7 Y' y! ]
  36.                                              cmdtype=NOCOMMAND;//如果没有,就直接返回00 W7 f0 \% W; h: G9 M- t6 O
  37.                                     }( [- d9 h# _2 r7 m4 G( Y
  38.                                     else{
    : ?! _7 c& L6 `; f& o
  39. 3 u, n0 l: I! E$ \. a

  40. $ u  g9 ?* x% _5 `$ L- R: r
  41.                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
    ( |% ^2 s9 E6 I7 [0 {4 E8 _) V
  42.                                             if(!json_ack.ID)
    5 I3 N. i  M$ @) K. ]
  43.                                                 {
    7 ?  q6 b3 E* D
  44.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0- \$ P$ Q/ w3 j5 n$ S( [+ m
  45.                                                 }
    % n  U6 V& e8 |: [% ~) K* h
  46.                                             else. S6 M: a9 N4 J
  47.                                                 {5 i4 d5 a# j5 Q! S2 Y% N
  48.                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);
    $ l" G0 s1 _8 y
  49.                                                 }# S' {" j* `+ M. D
  50.                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");
    0 h/ H5 a# X8 V2 S
  51.                                             if(!json_ack.Time)
    ( X1 l6 v9 A; Q' ]
  52.                                                 {
    7 r- n2 |# }) q. m
  53.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    0 ]# b4 ?, i5 B+ d1 P+ Y. w
  54.                                                 }# A1 t, p5 s8 v! F' _8 g
  55.                                             else
    . k4 E+ C9 H' V
  56.                                                 {
    3 w; }# v2 P, F! u) S
  57.                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);
    * m6 J- b' l) o# v$ T  J
  58.                                                 }
    , t6 {0 J5 o. a9 h; Q& F

  59. ! |' C3 x9 M) H! m6 T0 z
  60.                                                 cmdtype=HELLO_ACK;//如果没有,就直接返回0
    2 x! ?: c; q1 b2 S+ T
  61.                                     }
    ! L7 ]/ S8 P* d0 E
  62.                         }" b+ a- `7 I7 x& Z5 B
  63.                     else9 p. H- ?$ w. L+ q
  64.                         {
    5 V6 ~. T! Y0 _$ l% _, P

  65. 7 ?1 V9 m( ^" z( N
  66.                             //运动命令& F  z; m$ h& R- b5 r. J
  67.                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");! w0 A8 X, C8 R/ u: N5 d8 W
  68.                             if(!json_cmd.Command). T" M# U* P2 Q+ H+ g0 U
  69.                                 {! K7 {- a6 z! h* ^9 P
  70.                                     //printf("no Command!\n");
    7 {/ `- k) k! C  m; S0 o7 i
  71.                                         //cmdtype=NOCOMMAND;//如果没有,就直接返回0
    " u  ]* p9 I: A  N; Q4 s
  72.                                 }
    # t3 Q6 M8 H% M; k( @1 G9 ^
  73.                             else
    * I' i# f: ~$ k3 @
  74.                                 {
    ) m" V; c6 o3 Q
  75.                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);" a" C5 _- H+ M" E
  76.                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);" P0 H6 q4 X1 {  y
  77.                                     //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议
    ( ]! B+ h. g' y: f- d# s2 g9 a
  78. ; E3 J, A" m5 _/ w) Y
  79.                                 }
    $ ?; q: B" e! k5 @
  80.                             //速度指令
    1 @1 n. p  @6 D% `
  81.                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");
    1 i2 X4 k$ Z( C) V
  82.                             if(!json_cmd.Speed)
    9 t4 Y# M8 n: F
  83.                                 {
    $ x$ G% G- d- T
  84.                                     //printf("no Speed!\n");
    - D6 D8 k8 o& I: y) X+ B
  85. //                                    cmdtype=NOCOMMAND;//如果没有,就直接返回0
    : r  F+ _9 f+ `' F* w6 h6 G+ G8 m
  86.                                 }
    , Z& [: x- M+ @9 C
  87.                             else
    0 h7 ^! T* b9 S% _" M: a
  88.                                 {
    0 @: L* X, f& G8 ^
  89.                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);5 M: f  M  L  I0 @! h% J+ m
  90.                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;
    4 ?) h9 E2 L* d' [: C* z
  91.                                 }+ l. c5 l" U8 _* X5 H: Q$ V8 B+ z

  92. ' t1 ~! `  |, Q0 v4 l
  93.                                 //运行次数
    ; N7 B& b9 C; s7 `3 l
  94.                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");) c' y$ m: ^+ z' u- i& M( @9 I
  95.                             if(!json_cmd.RunCount), w% n: r2 u6 g
  96.                                 {
    , m( J4 O3 w) z# X
  97.                                     //printf("no RunCount!\n");
    # q8 X, m+ g) Z3 m" k
  98. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0  ]: F( H  }5 I8 |
  99.                                 }( A: l2 n4 b! c/ a8 u1 W
  100.                             else! s7 ?! E( D& ?' x7 I# e
  101.                                 {
    ; [6 U1 Q% s4 O2 R0 `3 M( s1 w
  102.                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);' y+ y5 _* [  k
  103.                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;# e8 T$ j+ M3 B
  104.                                 }
    5 F1 N1 b2 Q2 k. h/ N% p
  105.                                 //开始位置
    4 ]& H% U* u: V8 e* _$ S) S% W
  106.                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");1 X+ d9 z8 w4 H4 p' {
  107.                             if(!json_cmd.StartPosition)
    0 A0 v" z' _6 Q) @
  108.                                 {
    9 a- b& k  m3 ^) f' f
  109.                                     //printf("no StartPosition!\n");; H6 L, r/ i7 a2 f2 p; |8 t
  110. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0% ?6 f) J9 V* r! J2 g0 K! d
  111.                                 }
    ! p0 x/ X6 }1 O& M, M# K
  112.                             else& v5 b( G& T# e! h
  113.                                 {& \' f8 E6 G8 o
  114.                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);
    0 Z1 y! U$ e; q! ~9 z
  115.                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
    5 S& i8 z# B7 x' _
  116.                                 }- z. m3 A# n1 ^6 w1 z
  117.                                 //结束位置
    $ |3 F9 `0 W, s+ q% l8 V. i7 J1 `
  118.                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");
    9 r' `# s2 \, j  J
  119.                             if(!json_cmd.EndPosition)
    - d& ^* u- X/ W4 c  l
  120.                                 {* A+ l0 R/ N. v; ?- M( t) p- J
  121.                                     //printf("no EndPosition!\n");
    % ]; Q1 e$ C# f  j. e
  122. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    4 n% P# @% e' F/ Q5 m7 M
  123.                                 }8 z+ Z& z' d( D, y% W! l
  124.                             else
    / N, G7 W% W. f8 D5 Y0 I! M9 O
  125.                                 {
    . c: @2 `) w9 s. A6 h
  126.                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);& @1 Z: P9 ?6 d: w1 Q) o4 [; B
  127.                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;' m6 V9 {$ }# X# H
  128.                                 }
    " |: {, \. W( b
  129.                                 //目标位置TargetPosition
    2 ]1 x* t) t6 \6 ^
  130.                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");2 ^: v) U/ M# i% ?8 S  Z& _
  131.                             if(!json_cmd.TargetPosition)
    % T! l4 I! t% ^! c
  132.                                 {  F. y% {, N, b: M6 c3 W* \# I
  133.                                     //printf("no TargetPosition!\n");7 X/ |0 A* I1 F) e, m
  134. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0# R' j" S: {, M  g# O, O9 e
  135.                                 }
    & o$ @9 c( `# f3 V% U8 [8 E; n' a
  136.                             else
    ; L1 R1 V# J0 Q" w2 V5 Z& e
  137.                                 {. b. h( F) V, Q, ~
  138.                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);
    2 e+ V# j6 n; @7 Y1 y+ _
  139.                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;8 \, x0 t; S: [0 P
  140.                                 }
    # }$ x8 l+ c4 w6 n

  141. $ ~" A* B+ x; h
  142.                                 //*工作模式WorkMode;6 t. }5 A: ~0 |; F' l
  143.                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");% V. A! ~. n0 ]- a
  144.                                 if(!json_cmd.WorkMode)% }/ |+ v3 K$ Y5 Z" t& A( h1 N
  145.                                 {" M0 ~9 V% J7 ?* m9 [
  146.                                     //printf("no WorkMode!\n");' K1 Z( Y* }. K8 C/ k9 c8 a8 k. e
  147. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回03 R0 P  V& F8 u; w# P6 T& A
  148.                                 }" w  i# ]+ [* n/ P1 m) S
  149.                             else$ _' [  ~4 g3 ~2 V% Y' {4 D
  150.                                 {+ }# ?( Z, o% ~! }. G5 H
  151.                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);
    # I, {$ y. t8 S3 V$ d# H7 c2 w
  152.                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);
    / E' p% p' o- P# s4 O3 U( B
  153.                                 }& n" `: f: t' |( k- {
  154.                                 //step
    - I1 w0 g& z+ Y6 g' E" l! z1 }
  155.                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");+ g7 O/ q$ I4 |1 m" J' w1 j  ?! Q
  156.                                 if(!json_cmd.Step)- r0 }( h3 Z3 q* t. g) R% A
  157.                                 {
    # L- Z' e2 w: s: n
  158.                                     //printf("no Step!\n");" }: @1 p2 U  ?  d* d
  159. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回09 U9 \) N6 ]) s6 g, X/ @
  160.                                 }6 i4 Y2 N) y! `
  161.                             else- x) g8 A7 s* @" j3 z; s# V5 O
  162.                                 {
    4 x: M7 K  I2 y4 x& l; r5 }( m
  163.                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
    ( s$ X" K. m, I* s- p
  164.                                             Cmd_From_Server.Step=json_cmd.Step->valueint;
    " i. x$ P2 K* M/ t! B
  165.                                 }2 X; c1 {& ~+ ^  J$ s
  166. 3 x0 d- l( Z6 O# \& U% }
  167. 6 ^$ ]0 Q# M( f
  168.                                 cmdtype= COMMAND;
    + J; E: F4 m) k1 X1 g' b
  169. % e$ T1 T6 D6 O1 V' w4 _
  170.                         }, B1 O- d* l: c+ ?9 e
  171.              }
    ! k7 ~- ~" \+ l
  172. ( Z5 R4 w: p1 E6 N2 i( |- }
  173. cJSON_Delete(root);
    . D5 g% K9 x( _* X; @/ z/ U

  174. 7 R( R2 k+ T$ g. [7 P
  175. return cmdtype;8 R! S/ C  G! A% G1 g
  176. }
复制代码

9 K, n' ]5 ]" K. r0 ~& e) R4 I2 R) L- |, g) H0 F2 }9 d. Q
收藏 评论0 发布时间:2022-1-28 19:01

举报

0个回答

所属标签

相似技术帖

官网相关资源

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