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

【经验分享】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字符串. D+ f3 }2 _* n" f
  2. 7 V6 _1 w& |1 K  A2 m% ?/ b: K
  3. {
    % N( C5 I5 a9 {3 J4 w1 |) X3 m
  4. - o: X$ Y2 r# \/ T# t0 O4 W: \
  5.       char *result;" `, n, ~5 b7 Y/ g: n  [) t

  6. / W: c% R$ C: s* J( q
  7.       cJSON *root,*subroot;//新建两个cJSON的对象指针
    6 S3 o, D% @. H$ L; L
  8. 5 @8 ?) }  z0 C* D" z( b- M: d
  9.       root=cJSON_CreateObject();//创建一个机器人状态的JSON对象, |, N; x; J' @
  10. / W' O& q" n- p
  11.       subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象  w' H" C+ u3 s4 A' y+ w5 s
  12. % @9 O# u& F* N& J# |+ e
  13.       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。! L3 g  Q& V$ Y: {' o1 ]
  14. * k% K7 a) Q# c; u: B# F1 G
  15.       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);
    ! C' y  d. i$ U+ o
  16. 0 g& w5 C+ Q; [! K, r
  17. //同上/ F  A, b7 e8 u

  18. ! Z6 ^$ O% `/ I2 I- z
  19.   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);! K7 t1 u* C9 ~! Q/ ~2 ~
  20. 3 G1 G) {- m/ p+ C3 Q3 {
  21. //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型
    ( c2 W! ^3 g( \; `% [6 g) r
  22.   M% Z5 U9 a/ r+ ?6 t
  23.       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);4 a; h1 e2 y/ d) ~( O% Z& m4 [& C7 X
  24. 4 p) S5 [, G# i
  25.       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);
    + |4 }. j" J0 |" A( P: {

  26. / F: X$ z. t/ p! c* e0 r
  27.       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);) m, P8 g, }2 k  p

  28. 7 }7 \# C$ q7 u# p
  29.      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);( a3 }# X  s2 p; p9 z! a) q

  30. : I8 z2 P+ [+ X2 P- C
  31.       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);
    ; M8 X4 C( I7 u' y

  32. 5 E7 j/ \  X, W
  33.       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);6 [: L5 v0 N# M( A/ W8 R; ~4 K+ ~
  34. , k1 \) q- E2 s2 o, D8 a
  35. cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);
    $ Q- ]- r: s6 E- v+ S) E8 N. q

  36. 4 h3 J6 |( Q  O9 r2 P7 z! a' X
  37. cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);, B: c: E* P& M1 W* X4 C9 u

  38. & O7 X2 x; S8 J1 L5 M
  39.    cJSON_AddItemToObject(root, "RobotStatus", subroot);
    8 p7 ]* U; I4 N& S, R

  40. " ?8 J9 @$ C4 X" X; q# |
  41.       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间' _8 `9 r1 n5 b, L: \' l

  42. + e5 x0 Q& N7 B' d  D2 d. a
  43.       strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量, C9 E+ w' ~- o1 E

  44. ! D6 \$ L3 y; e4 M
  45.       cJSON_Delete(root);//最后将root根节点删除- J, n. p" D: Y# l% {) M" G% ?
  46. $ I1 Z' B, ?6 y: D' E
  47.       myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃5 l4 E% d6 _9 |' m
  48. 9 t% g$ k. |: r
  49.       return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。
    8 ~! v! A: l+ A& N. Y6 E8 b

  50. & i5 V4 ~# x& F3 \8 g; N
  51. }
复制代码
注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。
  1. #include "malloc.h"
    4 r7 l  R8 e0 R  o
  2. - j. V$ h' g# Y0 N( \: H6 [7 j& ?' O2 x0 K
  3. //内存池(4字节对齐)
    - [) m# Z( E$ p
  4. __align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池6 n! M3 w' E/ d. V8 q% p
  5. //内存管理表4 s. g4 m) J1 w9 |) k  I/ r
  6. u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP
    $ J$ y  p" J$ y: k+ D
  7. //内存管理参数. u( {) I5 v4 S* e$ @6 r' C  n
  8. const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小
    - e- ?* m' h- i0 Y& o
  9. const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小" w+ X# e; n4 |! g9 }
  10. const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小: q) W, H0 `1 H

  11. / J: o! q  U, [5 v) g- w1 i) n
  12. * w$ A) _9 z  t3 n5 k
  13. //内存管理控制器  H. }" t3 x9 u& }
  14. struct _m_mallco_dev mallco_dev=
    * @2 X/ b5 P+ d/ ~
  15. {/ `5 K$ ]* p' z8 [5 d: J: b
  16.     mem_init,                //内存初始化7 k; w% T  U9 m* o2 `2 [* ?
  17.     mem_perused,      //内存使用率
    0 d4 A4 ^3 o& ~3 k" a1 x
  18.     membase,            //内存池* }" X- y9 z$ L: H) R+ Y% R1 a
  19.     memmapbase,     //内存管理状态表  A7 F: Q3 e9 D. p' j  {4 w4 o9 D
  20.     0,                        //内存管理未就绪
    4 z/ g% L1 G2 ?% w9 k3 `1 S
  21. };
    $ Y5 q; a4 p& s: m

  22. 6 c, [9 c& M; f+ L. |% U9 w
  23. //复制内存* b1 D4 Z& y' j8 ~# @* R  I
  24. //*des:目的地址3 h) Q( ]9 `. h/ b' K  B8 h
  25. //*src:源地址' M' \: r4 P% c( D  C8 ?- i6 w+ j
  26. //n:需要复制的内存长度(字节为单位)
    % T4 E8 A1 x' G
  27. void mymemcpy(void *des,void *src,u32 n)
    ; `6 _' P3 \' ~0 M/ h( H
  28. {
    . @( n+ h8 G' [$ [0 T; }
  29.   u8 *xdes=des;3 k' z2 O2 c9 Z8 p+ `2 W/ G
  30.     u8 *xsrc=src;
    8 P5 C  G2 F1 \! I7 g2 R+ s
  31.   while(n--)*xdes++=*xsrc++;
    / U/ @% n/ j7 K% Q
  32. }
    - k$ t# m/ P6 y! j5 H
  33. 2 ]- e; J4 N" A9 u* {
  34. //设置内存
    $ Y* L) H1 }' P9 z  E+ L: I
  35. //*s:内存首地址
      F0 j" P) H& d2 ?7 z
  36. //c :要设置的值
      ~: u( @4 ]- I
  37. //count:需要设置的内存大小(字节为单位)7 s) f, O2 Z6 }8 P
  38. void mymemset(void *s,u8 c,u32 count)
    ! [  m! \% @5 l
  39. {  j' I) w2 W. O- Q7 Q. K, U
  40.     u8 *xs = s;" }9 X& x+ m. V' u
  41.     while(count--)*xs++=c;
    ! U% H( u, r( H& _
  42. }0 y8 q9 O( q. Z& g4 z4 v
  43. 7 r. w4 D$ o$ c# c
  44. //内存管理初始化
    ) F1 M9 W( a. ^+ \- n" p
  45. //memx:所属内存块
    9 }5 {. _2 M% \) q8 V9 y
  46. void mem_init(void)7 E( B1 q* q$ Q7 C: `6 L
  47. {; T' X* t; X# c2 T0 H! \
  48.   mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零# R: H8 |$ U+ K, D
  49.     mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零# _# h" ]% K" f2 \  q6 R) _
  50.     mallco_dev.memrdy=1;                                //内存管理初始化OK
    5 F7 V" b: q& Q, ~5 S  w; R* {" p
  51. }) T# v6 ^; |; R( k6 ~: x
  52. ' I. t8 M* x& l, D+ n0 a
  53. //获取内存使用率4 }0 `- p" d9 K! f2 l$ r! x
  54. //memx:所属内存块
    . f9 J9 E. i" u/ [: u9 L" A
  55. //返回值:使用率(0~100)
    ) |# n8 q. r( j  U( M. h
  56. u8 mem_perused(void)! @$ }! ?2 z3 Q: o
  57. {
    5 X, f/ n, ~* B
  58.     u32 used=0;
    + L2 }1 y  g) g3 X
  59.     u32 i;' D4 \7 V0 s, b% _) M, g$ _
  60.     for(i=0;i<memtblsize;i++)
    # c: l0 E) S; G0 m) R
  61.     {/ t5 Q) u' d% W/ t
  62.         if(mallco_dev.memmap[i])used++;; M4 r( u! F: P+ o+ l1 K
  63.     }
    . L( A+ j: l% Q' R% I" G
  64.     return (used*100)/(memtblsize);
    ' |% ^6 T/ K( Q9 n) B
  65. }$ U; }0 t3 o3 {  Q  ^( H* Q- k5 y
  66. 9 \; B/ o* z( z6 [: v$ t" e
  67. //内存分配(内部调用), U' q& _* r/ D
  68. //memx:所属内存块
    ) g% |% {7 _1 Q% l2 S# C
  69. //size:要分配的内存大小(字节)
    ; i7 {" w  }9 t+ v  T1 {1 R4 H6 W6 {5 k" `
  70. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址, J0 P' v+ j- e+ t
  71. u32 mem_malloc(u32 size)& C) W, F; Q/ C; p7 O5 I
  72. {
    ! w7 Z) x* p0 ]+ r9 J& D8 j+ e
  73.     signed long offset=0;$ B4 C' ~& v0 s( d
  74.     u16 nmemb;    //需要的内存块数0 i) L# }" Z% W
  75.     u16 cmemb=0;//连续空内存块数
    ) i2 s; A% X- c/ O1 |5 ?, [
  76.     u32 i;  L% y/ |  v) x/ d- j
  77.     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化
    2 O% M- g9 r; P7 I- ]" p1 ]
  78.     if(size==0)return 0XFFFFFFFF;//不需要分配
    * x: p" n1 P' v; s( f+ P) i( a

  79. # U2 W& s7 w- w- ?# \! K
  80.     nmemb=size/memblksize;      //获取需要分配的连续内存块数
    9 o+ |, y4 a8 F1 T$ G
  81.     if(size%memblksize)nmemb++;" U* T/ _$ n1 [. Q6 U2 z! D3 l
  82.     for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区
    / z# _/ X. H# P' x- F! |6 G
  83.     {
    6 G: P: \' w# x4 }) }6 F, D
  84.         if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加: q& Z. J1 C- I8 d" G+ s8 _
  85.         else cmemb=0;                                //连续内存块清零" a/ q1 n$ y  }# R) L
  86.         if(cmemb==nmemb)                            //找到了连续nmemb个空内存块) s% G: O" S. U/ G0 v
  87.         {% o8 }; K/ H/ w4 a% \4 j* u
  88.             for(i=0;i<nmemb;i++)                      //标注内存块非空
    + j( c! X* d2 O$ a9 \
  89.             {8 B; r; ]$ n+ }& k2 @( z
  90.                 mallco_dev.memmap[offset+i]=nmemb;
    2 `6 _4 A$ ~/ E) m, ]4 U3 X
  91.             }8 n- U6 }0 Z$ l, R
  92.             return (offset*memblksize);//返回偏移地址
    ' ^8 E  P, X3 \7 R. W$ p
  93.         }
    8 X5 t5 L' L" e0 k* ^6 s" x
  94.     }/ |* w& Y7 L1 V" A" n6 F
  95.     return 0XFFFFFFFF;//未找到符合分配条件的内存块/ l( O7 t1 ~; H, S( t$ e! y
  96. }
    8 y' T/ N: Q: P
  97. ) y& h! j2 j% O) M+ c1 e, U
  98. //释放内存(内部调用)8 Z0 s, W, X! @4 B/ m" r6 w
  99. //memx:所属内存块
    4 l+ d; Z0 \& v2 z8 l: ~8 }( m
  100. //offset:内存地址偏移
    ! n1 T  Z4 \: f8 `9 {9 l5 }* s
  101. //返回值:0,释放成功;1,释放失败;7 H9 f% o- ?* z1 i/ L4 N" w; X. |
  102. u8 mem_free(u32 offset)3 B. ^# d* h/ A% e: F
  103. {* S0 ]/ B$ D9 v# X) N
  104.     int i;+ q8 c( e6 X( l7 R# ~" s& r4 Q( U
  105.     if(!mallco_dev.memrdy)//未初始化,先执行初始化! F# k1 a$ ~. k' c7 G' x
  106.     {
    5 \( s$ y. o! R4 o2 F
  107.         mallco_dev.init();" S. m# K& C5 `
  108.         return 1;//未初始化, d; R3 v6 c; Y( g9 L
  109.     }% Y5 O  ]/ C- L* O8 `4 C
  110.     if(offset<memsize)//偏移在内存池内.
    / h: n  \7 b. [% r& k
  111.     {# v8 C/ o9 G5 e& E% r2 y) [1 v
  112.         int index=offset/memblksize;            //偏移所在内存块号码& A2 I- j, a4 O/ L
  113.         int nmemb=mallco_dev.memmap[index];    //内存块数量
    " p5 U0 ~) v0 U, B
  114.         for(i=0;i<nmemb;i++)                          //内存块清零
    4 A6 n& m4 _1 f% V' {) w8 G
  115.         {: {! `, @/ a' a4 `6 j/ z
  116.             mallco_dev.memmap[index+i]=0;
    ( X, R" p- p) M0 U. i
  117.         }
    0 n% ?" x  s; ^6 e
  118.         return 0;
    ! O* U$ y4 M+ a) W) `
  119.     }else return 2;//偏移超区了.
    $ m. q8 `$ `& w' K) Q4 w1 S* I
  120. }
    / N3 `6 r7 A  Y+ S5 g

  121. 7 s. {; P7 a2 u1 i
  122. //释放内存(外部调用)
    * V  w9 Z- |) s1 b
  123. //memx:所属内存块
    9 o) V" a: S3 O7 K, w( Y; I. C
  124. //ptr:内存首地址
    ) @" Y$ e2 _& X* H/ M( T- z- e
  125. void myfree(void *ptr)
    7 P' r1 J1 w4 G! b
  126. {
    2 N8 {9 B" h# z' Q; t0 o6 ]8 j
  127.     u32 offset;! `" z( v7 p" m! q% K/ M( D
  128.     if(ptr==NULL)return;//地址为0.+ @+ v, [) p6 T) L+ U# H/ \9 m7 a
  129.      offset=(u32)ptr-(u32)mallco_dev.membase;
    / ]! l+ g( c5 k
  130.     mem_free(offset);//释放内存
    $ \/ x8 }$ ?- m! v& U- @
  131. }+ Y% [# a* c% V" A% N+ H: T. z5 Y

  132. . K# X( U( l& U
  133. //分配内存(外部调用)
    ' o0 R* E: ]: j9 W' \* i$ C
  134. //memx:所属内存块
    , [) W* j5 `9 l0 ]3 f: n
  135. //size:内存大小(字节)1 y' O; J$ d$ w/ c/ O1 U& `! B
  136. //返回值:分配到的内存首地址.
    / V! g0 C" r) \. H3 k4 Z$ f
  137. void *mymalloc(u32 size)
    0 q; {. K* L9 k& s6 F6 a6 g2 d
  138. {
    $ v3 |2 F; B3 [, S. W
  139.     u32 offset;
    2 C% ~4 k  S! J5 j
  140.     offset=mem_malloc(size);; O  V9 |, e" o3 t6 N! W
  141.     if(offset==0XFFFFFFFF)return NULL;
    * I1 i! O5 C: l# {, O7 `
  142.     else return (void*)((u32)mallco_dev.membase+offset);4 s% _8 `1 z7 c4 ]+ G* |: r
  143. }# c  h0 U2 w* T' n9 B

  144. * j# Y0 P7 p- B4 u  @0 W. N8 }
  145. //重新分配内存(外部调用)* F, F( \( `7 k- q/ \4 p
  146. //memx:所属内存块
    7 Z% A) S9 [3 t9 x
  147. //*ptr:旧内存首地址
    6 k2 b7 j4 _! s
  148. //size:要分配的内存大小(字节)
    % x, h8 I3 L3 B' l* T
  149. //返回值:新分配到的内存首地址.
    1 P$ e# N, ?2 S" F3 v
  150. void *myrealloc(void *ptr,u32 size)9 z8 G. H! ~6 a; h2 P1 @, f' o! z
  151. {
    ' x9 H& S. E% t
  152.     u32 offset;& }* y0 d, M5 w3 p
  153.     offset=mem_malloc(size);
    0 x; p. l* @$ q2 r
  154.     if(offset==0XFFFFFFFF)return NULL;
    % Q6 {4 ~; f9 H- z. w$ ]
  155.     else4 A( g! z) v: u& c& Z  e3 J
  156.     {. f8 e8 b4 |+ P( [  E
  157.         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存3 @* y9 D) r& P, U  r5 U$ H! X5 ]. z
  158.         myfree(ptr);                                                        //释放旧内存
    3 ^6 d. O# v$ x3 X
  159.         return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址
    7 l4 I9 G- f5 b! a' y
  160.     }
    ! l; s* s/ A* l/ q0 @# k5 \: b
  161. }
复制代码
malloc.h内容如下:
  1. #ifndef __MALLOC_H6 V* Y1 ]* g1 l- C' E3 O6 {9 ]8 s+ d
  2. #define __MALLOC_H( `3 g3 W7 m$ Z" W3 ^6 T
  3. #include "stm32f10x.h"8 `% b: i" s& W3 R: |( V; B2 s0 M

  4. % C+ a" o& e+ a6 ?/ H
  5. #ifndef NULL7 A9 {1 p. n/ l: v0 V# m
  6. #define NULL 0
    & G" ?% j: o2 J8 c* e: r. g
  7. #endif
    ! P5 L+ ?! H- o# \
  8. . l# K, V& }# l9 [: [1 t
  9. #define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节
    ; {; D9 W: ~# y+ Y  E
  10. #define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K
    ! Y# k$ u$ W5 F( o
  11. #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
    & `3 j' z1 d3 _
  12. 0 D0 M, |- r/ S5 s) M+ @! C
  13. //内存管理控制器
    & O/ `2 R/ P$ y  o% e0 Y8 {
  14. struct _m_mallco_dev( n5 @9 \. x5 k5 r. _* [
  15. {
    0 i- L6 a% l! ]
  16.     void (*init)(void);                    //初始化
    3 j& ]3 k7 x/ I: h
  17.     u8   (*perused)(void);                      //内存使用率
    - z/ J. X$ d! t
  18.     u8       *membase;                    //内存池
    # s( o; K: a- |. r. ~1 ]
  19.     u16   *memmap;                     //内存管理状态表2 }( A! g. A) [) V
  20.     u8     memrdy;                         //内存管理是否就绪
    , R4 r6 l% F: @& Q
  21. };) A6 a& D! j* u- n! {

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

  3. ; I3 ]( Q) k8 g5 S) `2 v: s+ B. X8 `
  4.   Permission is hereby granted, free of charge, to any person obtaining a copy
    - Y! d& I3 O/ I; r$ e
  5.   of this software and associated documentation files (the "Software"), to deal2 o0 Z8 S$ x- i0 P
  6.   in the Software without restriction, including without limitation the rights
    ; k: Z2 n( P% J$ |8 Y. K) S8 H4 M" i2 r
  7.   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell; ?9 {3 S5 k; |6 z
  8.   copies of the Software, and to permit persons to whom the Software is
    , W. i% I- t7 E3 x. r# u0 D) A
  9.   furnished to do so, subject to the following conditions:
    + w0 t3 u: z3 T1 B+ X9 ^# _+ y* r! f  D
  10. " V) K# B! q$ u
  11.   The above copyright notice and this permission notice shall be included in
    % o0 F% N. r0 {
  12.   all copies or substantial portions of the Software.
    . J, ~: R; F8 n9 M1 G1 D

  13. 2 r- M" K- M4 s( z* O1 J3 B: a, B, }
  14.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR: V% z7 _; p4 z! n: Q
  15.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,) o& |2 t' J6 l0 x: x* P% X# O
  16.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    / |! M, |  v  Q0 D
  17.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER& ^7 k0 k; m- w- Y/ J
  18.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    - Q3 a* m' @* O& {1 _
  19.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    & e5 T* u# x1 a0 k2 U
  20.   THE SOFTWARE.
    2 Z& f8 f$ c, O* o( v2 C$ \
  21. */5 n& |" {2 }$ a. H2 e. n# }' ~

  22. $ t6 M. K2 C. P
  23. #ifndef cJSON__h
    ' K) r6 \& T6 z
  24. #define cJSON__h" R& b+ L$ T2 a2 r2 _& [! C
  25. ; e; P7 G' T4 u; H* d
  26. #include <stddef.h>
    ( A# D, u+ i# u6 ]

  27. : A5 ]0 k1 h) b* T; @7 O2 T5 r9 W6 T
  28. #ifdef __cplusplus, y3 b1 g% @+ T$ Y+ t7 j* e
  29. extern "C"7 c: D1 n6 [% o7 V+ o$ U( `/ @9 E
  30. {
      A! H4 e# D$ v
  31. #endif# g! m( N/ t1 v% e; j4 D
  32. , X# H+ f) X; N, a- s) g
  33. /* cJSON Types: */- D3 d8 c+ J' f0 \# R2 W  x
  34. #define cJSON_False 0. k6 ]1 n$ F; C8 A
  35. #define cJSON_True 1# s* i, o2 L; p$ F0 `
  36. #define cJSON_NULL 2
    - R. v9 I# Q! {& a" O5 c3 n) \
  37. #define cJSON_Number 3$ I( S! D( i3 w; B  S
  38. #define cJSON_String 4
    + W( K2 R5 O$ L
  39. #define cJSON_Array 5
    * i8 ]! u0 a0 R! v
  40. #define cJSON_Object 6
    ; B$ a) b5 a; i4 P4 q, w
  41. ' F% J8 D' Q. W; Q$ U
  42. #define cJSON_IsReference 256
    + e# a/ |8 Q" B6 X) |  p
  43. 1 I3 M5 @' |1 t2 r
  44. /* The cJSON structure: */) t5 i+ L( J- _, q6 E, V
  45. typedef struct cJSON {
    & ?/ |* P$ f* @  w7 p6 X, v6 l
  46.     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */% k$ ^5 c5 j3 J2 b  i
  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. */
    - g2 {* W- `. @) l' `# [

  48. , c+ l- |! L: V
  49.     int type;                    /* The type of the item, as above. */
    ' i: P+ @1 [- W2 Y/ n3 l

  50. . z* a0 {- n5 \; }4 S* q
  51.     char *valuestring;            /* The item's string, if type==cJSON_String */
    / K3 x0 s5 n0 v" A
  52.     int valueint;                /* The item's number, if type==cJSON_Number */
    - c& l/ |; t- E
  53.     double valuedouble;            /* The item's number, if type==cJSON_Number */
    0 o6 j8 @, |( T8 N

  54. * V; U7 }. I! C# b3 j7 h
  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. */' i* c4 ~6 ^! m; y5 I9 U8 S7 J
  56. } cJSON;
    / `# e$ V9 E' }& j

  57. ; s# {6 A5 U4 u0 |) B: n- r
  58. ( f7 p$ E8 |: C1 H7 A3 A
  59. 1 h1 v. j- o; _2 Z; V: M0 c4 Z
  60. typedef struct cJSON_Hooks {4 [$ o  }- y2 W. r6 [+ @) H( y
  61.       void *(*malloc_fn)(size_t sz);5 r/ U/ Y- G4 p* b( i6 F6 ]5 G, o
  62.       void (*free_fn)(void *ptr);
    , [3 ~, ?. D/ b- X  ]
  63. } cJSON_Hooks;
    ( ?; }# t: P" T# d

  64. 1 o3 }3 \1 C* K' T8 F9 s& o; r& b+ |
  65. /* Supply malloc, realloc and free functions to cJSON */
    3 ^+ R2 E( `; U. u$ N" s
  66. extern void cJSON_InitHooks(cJSON_Hooks* hooks);
    6 L5 v- w6 {- M3 C( @
  67. / \; }2 }/ b" y3 J$ |

  68. . l; ^7 u- I, V6 N+ A1 L
  69. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
    . E# r! f) ?; i5 P( k5 ~% ^
  70. extern cJSON *cJSON_Parse(const char *value);( X$ x1 \0 ?- o6 z: u
  71. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */! s5 S" O9 j5 w8 w% F9 U1 N
  72. extern char  *cJSON_Print(cJSON *item);
    # \. N8 c7 Q6 @) k* J
  73. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
    9 R+ I: d* }  K2 T! W. S5 E1 D
  74. extern char  *cJSON_PrintUnformatted(cJSON *item);
    1 y; Z% A9 S. ^) n# h' K
  75. /* Delete a cJSON entity and all subentities. */
    7 L+ e; `: y( |* X  o% }
  76. extern void   cJSON_Delete(cJSON *c);1 ^2 v% E+ b5 A, h
  77. ' c; |2 D2 V) n! Y1 p3 `6 L& \
  78. /* Returns the number of items in an array (or object). */
    % f2 I: v5 B5 G* O8 ?  W
  79. extern int      cJSON_GetArraySize(cJSON *array);
    2 p& n: l1 S7 o
  80. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
    ( f" X* y6 @, `! ?! b9 H# @& e
  81. extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
    * B; C3 ^: f7 d7 u6 j: ^$ U
  82. /* Get item "string" from object. Case insensitive. */2 i1 J( ]$ c0 z3 O
  83. extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);' ~/ I) `3 r' t1 e- [  z4 V
  84. 0 L8 r& d9 h$ L# i2 a" J
  85. /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */0 v0 _9 n4 p! ?& L
  86. extern const char *cJSON_GetErrorPtr(void);
    . T' D: }* S2 D+ w% @" e  k0 M1 J
  87. 1 f+ J' }6 t$ j; ?& @
  88. /* These calls create a cJSON item of the appropriate type. */$ D7 ^4 u- B) q- Y
  89. extern cJSON *cJSON_CreateNull(void);# j4 |5 D. o5 N- G$ Z
  90. extern cJSON *cJSON_CreateTrue(void);
    1 S: N1 M, t/ x1 `
  91. extern cJSON *cJSON_CreateFalse(void);- x9 c" h/ m  }' C3 H
  92. extern cJSON *cJSON_CreateBool(int b);! u5 H& V" S1 b+ t, [
  93. extern cJSON *cJSON_CreateNumber(double num);
    8 {2 \4 c6 _- ?! S: j  I* W
  94. extern cJSON *cJSON_CreateString(const char *string);; z& k6 C- o; N) A" d
  95. extern cJSON *cJSON_CreateArray(void);# Y. @4 H. ~4 Q4 @% r
  96. extern cJSON *cJSON_CreateObject(void);0 R& D3 _1 v* l- f& S. {
  97. * b: J& E$ o( k. [" A
  98. /* These utilities create an Array of count items. */& O% @5 Q: f+ r( H
  99. extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);$ y/ |+ A: }" k4 ^# ]6 ~/ V
  100. extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);, R8 r3 r5 i% t
  101. extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);+ ]: d0 G+ R$ w0 `- z$ q- `( C
  102. extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
    / p6 ^' L& R: J
  103. - t$ Z: A) I9 }  ^  F: t0 P# d
  104. /* Append item to the specified array/object. */
    8 J( o& q% K2 P# A) I+ P! z2 ~
  105. extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
    " B* e( l$ I& q) l: s
  106. extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);0 p' c) N+ s" {4 ^8 ?; d
  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. */
    8 Y! N: P4 y6 W  o9 c. a9 F1 @
  108. extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    & ]- c7 |/ i" @  A  t- j
  109. extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);# @5 Q5 F* B9 z: V/ h' s

  110. " W5 \! {1 b) m2 ^) o
  111. /* Remove/Detatch items from Arrays/Objects. */# K4 ]- T8 A* w  w4 ^
  112. extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
    $ t6 |& A% a: n( u0 E0 N1 _
  113. extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);0 N! u; i4 R5 {. ?& F& H$ Z3 Z" i
  114. extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
    & r/ c6 \, u3 K! O' F
  115. extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);# I7 S3 ?* @& U$ A# p) R
  116. ' M- N, C- G' N( f
  117. /* Update array items. */2 _3 O. g! F) A+ N+ a2 }
  118. extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
    ' Q) s, X8 _; S7 v
  119. extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);/ y# B' d# k2 R+ s
  120. ! Y5 @5 d$ F5 }6 S
  121. /* Duplicate a cJSON item */
    8 D" ?8 g) z" w
  122. extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
    ' W# b" y$ ^( `/ j4 i  F% f
  123. /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will. L0 u/ t- v+ ^% \  m
  124. need to be released. With recurse!=0, it will duplicate any children connected to the item./ H; G$ ?3 K" i. j0 U
  125. The item->next and ->prev pointers are always zero on return from Duplicate. */
    4 n# ]7 l2 N1 S% X
  126. * {% V1 j) C+ P3 p
  127. /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
    & v$ Z9 ], M9 {4 s4 j) v! o
  128. extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
    6 T& y  S5 X' z# [! n9 \) [

  129. % o+ a0 Q6 N% _5 N) p$ h
  130. extern void cJSON_Minify(char *json);
    : G/ d9 b( L/ x5 x
  131. $ A5 |: s+ p9 _' b
  132. /* Macros for creating things quickly. */! n6 T( m1 k2 e1 t9 F
  133. #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())8 ]" P' h: b, V9 K4 d, k0 E$ M
  134. #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue()): \+ t: V/ \) v, {& T; v- x
  135. #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())) ~6 K/ ?& q) ~: i7 E% Z% @) P
  136. #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
    6 c0 F8 C! a2 X! u: A
  137. #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
    + p) \% q+ f6 I
  138. #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))# v, }  D. ~' T" @# _% @3 A" {+ e
  139. 6 D0 f- `; ^/ `* X& A& |( U
  140. /* When assigning an integer value, it needs to be propagated to valuedouble too. */( j6 C, t8 a" a1 W) l4 T3 T' @
  141. #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
    0 p6 J, x$ O! a$ l5 i+ G; I) V, c

  142. ' D/ l- Q6 K8 q8 C8 P8 l
  143. #ifdef __cplusplus
    + U1 c3 {7 W8 M+ ?# I3 j( r# b' w
  144. }- Q$ A3 j5 e2 k' u
  145. #endif
    ) ~4 \4 m5 ~7 u9 \5 b$ C

  146. 8 X/ w$ w$ ^" i7 c1 v8 d
  147. #endif
复制代码
下面是JSON数据的解析部分,简单说来就是对号入座。
  1. /**************************************************************************% m6 x# O  Q  L3 {
  2. 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令
      ?# D7 Z, u' @" r
  3. 入口参数:JSON格式的字符串,
    # d* X( w  i6 W
  4. 返回  值:指令类型+ t" Y  w2 K$ i; V! r9 m) b
  5. 注    意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数
    # i% G+ B" E7 d9 l5 w& R8 p1 ~# G
  6. **************************************************************************/
    + o" L, A- r! F$ q
  7. CommandType GetCommandFromServer(char * JsonDataFromSocket)
    ( L- \1 e% g; i* N- j
  8. {
    / b0 J2 K  J# r; ~) }

  9. 1 \" N2 x) Q1 m
  10. //  ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替- q: O, k8 T! i2 g: K6 c1 g" b( m
  11. " |1 |& j. w! M( X- i* m# V8 t
  12. //    Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替0 j* S  N8 w( M4 R
  13.     CommandType cmdtype;/ U6 \% Q  X8 g: {4 R3 l* x0 H1 t
  14.   RobotJSON_CMD_TypeDef json_cmd;
    * U; V0 ]* f! v& h* F- I
  15.     HelloJSON_Ack_TypeDef json_ack;
    $ s, S% E9 v  p( P: x

  16. 7 X0 p  [' z/ Q9 S) F) U  _
  17.   cJSON *root,*command_root;
    * s9 T3 Q( H+ c, W; ?4 I
  18.   J8 E% V: A& d
  19.   root =     cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)6 A! {: L+ I) Y0 r; c  l
  20.     if(!root)
    . A  `8 u  q. H1 h5 R( m
  21.             {( o# \9 K) D: E; B
  22.                  //printf("get cJSON  faild !\n");
    7 E$ v- c  Z2 g6 O
  23.                 cmdtype=NOCOMMAND;//如果没有,就直接返回05 I) K5 J* R  s7 [2 y9 r
  24.              }, m8 {/ [; B  S/ A' L
  25.             else
    6 k7 X5 \2 Z5 j+ T' W6 [; ]  l+ {( g
  26.                 {
    2 f9 x/ V3 v# s4 v$ R2 _
  27.                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对% O% U! {  g) _/ f: O* @# Y+ ]
  28.                     if(!command_root)
    $ J/ P; x7 {& d/ _9 b  f/ D
  29.                         {
    & M4 a) ?3 u1 r, i/ y
  30.                                 //printf("No RobotCommand !\n");) p* {6 j! ~9 B, z
  31. - G! r- S8 A- x# r, {4 V
  32.                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对2 M/ l) z1 L  D2 [5 {: I
  33.                                     if(!command_root); Y4 O% T! K5 a
  34.                                     {
    % ^0 c) X& ]( g5 e
  35.                                          //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回0
    ) w+ K, k& L, j2 F- R
  36.                                              cmdtype=NOCOMMAND;//如果没有,就直接返回02 C* u! I9 n) O) R: b+ [; b
  37.                                     }! F5 s1 n# F9 c% I9 ^
  38.                                     else{1 j* m( F' x) y: t2 y0 c

  39. 4 u0 x* b  ~$ a: M2 h

  40. % h% Z( }- k9 g8 J$ {6 K6 j
  41.                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
    7 r2 R' n: N9 w7 T
  42.                                             if(!json_ack.ID)
    ' f( s, x( }) y
  43.                                                 {& U5 T( Q% M0 ?: q8 {2 Q6 E
  44.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
      b# M1 S3 F1 F# `9 F3 C0 |! W. g/ t
  45.                                                 }
    0 ?/ c9 A+ K; ^
  46.                                             else8 O6 L( ~9 _$ r' q: |( N7 H
  47.                                                 {  b9 F+ @2 h( k3 R
  48.                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);9 u! q5 k! u+ P% [; }& d3 q6 b
  49.                                                 }' e1 K9 t. u" M+ h) z8 l* l
  50.                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");
    3 }9 w# K; J4 m
  51.                                             if(!json_ack.Time)8 q6 l! X! X5 a5 {/ v* `7 z
  52.                                                 {  r% M1 {& u! [- l+ q4 Q& n: l" \
  53.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    7 {# |, _. Q+ D, `
  54.                                                 }
    & h6 }* F4 |6 z" @1 ^  k
  55.                                             else3 K; ]7 C- X8 s7 Q/ B8 s
  56.                                                 {7 ?0 H; }5 `: b" R
  57.                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);
    ; ~  q- H# n* K4 K9 q5 M; h
  58.                                                 }) h/ V4 [0 C$ ^. O( R1 B6 R+ I8 I6 E
  59. & K% t- y5 R4 |* w* a) C: w/ O
  60.                                                 cmdtype=HELLO_ACK;//如果没有,就直接返回0& _! ]" P1 w, t" k7 K' a; `
  61.                                     }" H' d$ R( g, b* U
  62.                         }+ H7 a) O* Y4 d, {" G6 B
  63.                     else9 ~2 j" o* ?+ V7 ^8 ]
  64.                         {
    " ?2 e/ L8 \  S* O3 X9 \& b
  65. 6 P$ B8 ^/ r5 i( w& I/ C- W
  66.                             //运动命令
    * W: i- p8 O& [4 {* n6 B
  67.                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");# y8 C' U0 ?0 @2 s5 J9 `' _
  68.                             if(!json_cmd.Command)0 f" `& R  ]( g/ ^6 ~6 m
  69.                                 {
    ! }: w/ e6 }1 J, b4 G; \/ U
  70.                                     //printf("no Command!\n");6 k# Z! W( F) v, `& T9 q; i% i
  71.                                         //cmdtype=NOCOMMAND;//如果没有,就直接返回0
    % c, V; ]3 z# ]2 u5 Q* x: `
  72.                                 }
    3 s! U2 {" l. T+ U
  73.                             else/ w0 X0 n0 y" p3 ?
  74.                                 {) Y1 K/ E: k" ?. i9 x1 Z. I# Z  W0 E
  75.                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);; Q& n2 p% r7 B1 [" \
  76.                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);4 I7 y. [% D- B, F; b# b8 B* c
  77.                                     //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议
    % T; t! ^6 M  L! ]8 s& R. W

  78. ! n* c" f4 O. _
  79.                                 }- e# q6 l+ F* w  |$ d* T6 I: z
  80.                             //速度指令
    2 i6 m. b' u! G3 A1 h5 R. {5 a
  81.                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");/ P$ a# m: S# `, p- h
  82.                             if(!json_cmd.Speed)$ s3 O" M0 N0 o1 S9 n! n4 v, c
  83.                                 {
    . B' S( C* Q! [' w* x/ @2 f
  84.                                     //printf("no Speed!\n");. Q: ]2 m! ^) B* k+ D6 }
  85. //                                    cmdtype=NOCOMMAND;//如果没有,就直接返回0
    & v7 J! H, X1 R. f4 ~( R5 P
  86.                                 }
    ) b5 n3 J* M2 h$ ?$ H
  87.                             else9 P# \( P+ }' V# J/ ]
  88.                                 {
    : b9 {2 G7 A5 c7 P( p. t
  89.                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);
    # D) b9 X( J) ]
  90.                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;
    3 y6 ]7 @/ j4 {; a) Y
  91.                                 }
    ) M- T3 U' m: z! S9 M+ Q
  92. " f& i8 p% ~$ X& Z
  93.                                 //运行次数
    7 e1 j' s* m% x. D+ p/ D: {/ Y4 F8 d
  94.                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");
    ' E; _/ T0 q# O6 X1 b3 g6 ~: I8 I; y1 `. G
  95.                             if(!json_cmd.RunCount)' Y' x% s* J1 ~% z' }
  96.                                 {. w5 p# M; [9 N2 E7 f( w( _
  97.                                     //printf("no RunCount!\n");3 u& b" o# J6 o- |- Y# {6 Q" k
  98. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    % K+ A6 I% {# c8 S6 i* u6 k% s
  99.                                 }- Z' @) ?% D' C- L
  100.                             else
    1 k+ |9 I2 Q+ v6 k
  101.                                 {
    & i0 R! C2 b( C2 [3 k" V
  102.                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);
    ; b  m0 M6 @9 z3 ]1 I
  103.                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;/ ?) \2 G3 @1 `: r& c4 ~
  104.                                 }9 t' t/ e7 U8 {
  105.                                 //开始位置* ^/ A: y, U1 [* c7 T8 t
  106.                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");' X5 ^7 _$ d8 L4 ]. [" z- B7 c: u
  107.                             if(!json_cmd.StartPosition)
    % \) h( R6 x% A' @( S! E# O9 S0 z
  108.                                 {
    8 [& f/ Q, _. ~: G) ]4 a! Q3 {
  109.                                     //printf("no StartPosition!\n");- I7 U/ q6 t3 [7 }- B8 Q# t) A/ W8 }: H
  110. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0( Q, x" Z: V# c+ y2 {
  111.                                 }0 K7 Z2 Y3 n; l1 f7 H: M
  112.                             else
    5 `, @  n$ o. r. r. p$ M0 C5 ?; _* }
  113.                                 {
    , x. ~- |/ ~1 _1 v9 n& U* A
  114.                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);# X" t3 ?7 B% T6 S5 K3 z  M
  115.                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
    * Q3 i9 V0 g$ I$ X
  116.                                 }, v. S7 |: B/ \% y" k# T5 I9 o6 `
  117.                                 //结束位置
    # w! i/ Z, M0 a! c- c
  118.                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");1 h) D+ O5 z( y/ w: f
  119.                             if(!json_cmd.EndPosition)
    1 j* O& E0 T7 r
  120.                                 {
    7 \8 u3 a& I1 L
  121.                                     //printf("no EndPosition!\n");, U9 u- U- x: Z4 q. K
  122. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0- v, D8 v1 B+ u) }- p
  123.                                 }
      Y; I2 \7 Z6 e, `+ ]6 r" m3 Y
  124.                             else) ~! w  s4 O1 a( x2 L
  125.                                 {
    ; G5 M+ a. T$ V8 A0 F& V& ~
  126.                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);
    . \% }* k4 X! Q. x) [
  127.                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
    + t- t+ o) H- a$ |
  128.                                 }' M' x# g% l& ^$ h
  129.                                 //目标位置TargetPosition! V9 f6 Y# v2 Y
  130.                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");: y  D3 j! P' Y3 e
  131.                             if(!json_cmd.TargetPosition)
    + V8 z) N( G. q5 O) M* v
  132.                                 {4 D/ q7 q% j" E( r: h, m
  133.                                     //printf("no TargetPosition!\n");
    ; C! H5 v' `# E2 ]$ L) k
  134. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    7 f# H; ^" z) v* p( [  A8 x
  135.                                 }2 J! s4 L9 q/ N. U
  136.                             else
      J  |) t2 m& I" I5 ]. `8 g
  137.                                 {; S% }+ F: [4 d  g* ~# {
  138.                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);" @9 s, E3 _) r+ c8 C
  139.                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
    3 |/ \! }: o0 h! ^
  140.                                 }
    " z! [1 Y5 t$ f) y
  141. $ O% ^4 H# N% N( S. y+ I
  142.                                 //*工作模式WorkMode;
    9 N$ _4 W% B' u- u
  143.                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");+ l5 \5 ]) _/ Q6 ]4 N( o& y  ?
  144.                                 if(!json_cmd.WorkMode)7 d7 C: I: `/ B5 F& H+ E" p
  145.                                 {8 @. N! S. O0 a/ a( T8 M
  146.                                     //printf("no WorkMode!\n");
      L& s* Y7 Y3 A: X: I
  147. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0' z# d& n8 W4 f1 G
  148.                                 }7 U, C5 x2 p: \" s* D2 s
  149.                             else2 h  i- U: t7 e3 E" T
  150.                                 {
    1 [2 [. G! @  j4 J! Q- T
  151.                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);/ A5 u- ^7 T* F- Y& F/ Y
  152.                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);/ J4 {+ T' s3 Y9 K) \( O) [
  153.                                 }. m) x7 k1 e* C" d/ B
  154.                                 //step+ K1 n9 {" _0 J/ Q) y
  155.                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");9 L$ m& I$ n  b! o; ^! ?: O; i8 H
  156.                                 if(!json_cmd.Step)
    * I- Z! ]3 B% I9 M+ A8 A. M0 ^, O& S
  157.                                 {
    " G6 e7 W+ E0 B
  158.                                     //printf("no Step!\n");
    : V' m) F6 l& G4 R& G( @! @* S$ v. R
  159. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    ! n) I* p& ~# ]$ _4 `: t* x* x
  160.                                 }
    * a% q1 H! P0 S. W5 l8 [& }
  161.                             else% H" Z" [5 b* y" ], n4 r8 c3 b
  162.                                 {0 X$ P% y7 j0 |
  163.                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
    - }9 [" R/ P& R% M& Z6 r' M* l
  164.                                             Cmd_From_Server.Step=json_cmd.Step->valueint;
    9 e8 P$ S# p" x( M' R+ X; I) m
  165.                                 }$ Q3 i# W- o! d0 h6 l' u  K/ O
  166.   ], U- V  l+ B3 s  V. S
  167. . z1 L* E% A+ J- {' c
  168.                                 cmdtype= COMMAND;
    5 d' j) {4 O( U1 B! X
  169. 5 F6 |0 C' L% L
  170.                         }
    , D& z6 y) z  C7 T
  171.              }* T: J1 \# ?1 g' |" @7 f
  172. 2 R: _; l: s7 v. [; I
  173. cJSON_Delete(root);: S. u/ b! m5 u- T# F' ?4 K
  174. . v9 X; S8 {% q9 w9 e: u( @
  175. return cmdtype;5 \# R  G' H; D1 t/ a
  176. }
复制代码

, `2 n. T- j. W4 x( K) i- ~7 t' B2 x8 v3 `5 R6 z* Q
赞 收藏 评论0 发布时间:2022-1-28 19:01

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版