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

【经验分享】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字符串' ~# S7 L' l- n
  2. ' u, N( ?6 Z0 P4 I  E
  3. {
    ( a* J  Q+ w* r1 T3 M' h/ l+ [
  4. : L3 }  O1 c: z) q9 h, a) y. A
  5.       char *result;+ @7 }% n% S" @2 ^8 N
  6. ' e) H; d* b# y& ]5 E' T
  7.       cJSON *root,*subroot;//新建两个cJSON的对象指针3 c% W7 T" P5 s+ y- R( j" P

  8. # f* }, C! f  O  c. L0 N
  9.       root=cJSON_CreateObject();//创建一个机器人状态的JSON对象
    4 h' S3 w' I5 v

  10.   U3 Z, H3 u) a9 a) [4 t% ^
  11.       subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象
    ! S4 @! }( T( W! C, X

  12. / B3 N5 N/ ?5 g9 i
  13.       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。
    7 b  D5 H1 k* u# S  {7 V3 x
  14. ! C8 J$ E0 L$ F* H9 M
  15.       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);% T8 L& w) U, w0 N; b  _+ l

  16. ( y, J5 n6 O1 I; ~" \- k6 a, l
  17. //同上0 b4 l- J9 o4 B8 S* q* x5 n) \4 G
  18. ' h  l* W. G! e+ l, M+ F2 B
  19.   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);4 c* j7 j# v! }4 F4 x" f8 w$ o

  20. + |+ _3 O8 |" A! d
  21. //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型
    0 J) n- r+ z/ I( x1 ~, e4 O. w

  22. 2 g1 s6 n! m, I
  23.       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);) t) p. O# Y- D1 H& a
  24. ! _, s/ o! V6 h& e# E0 U; n
  25.       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);
    ' R! s$ n! U: W! ]4 X; S4 G, s' j

  26. ( S% j$ f( V( e: R; ?6 Q- d
  27.       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);
    : j7 Q+ s% i5 h/ [/ J; [* O

  28. 0 B# p0 C( D4 X. d; {" k9 g
  29.      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);
    & u* k. @7 A# C* x9 V3 ~  J

  30. 0 Y+ P: t! F9 K( A
  31.       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);: b- J7 ^2 q: P1 a% y* r
  32. ; v0 e1 i: j2 W8 W
  33.       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);
    * K# ~5 a" Q5 z

  34. # M; e& n, ?! M- i! a
  35. cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);: \7 V2 E$ F# w: k- m
  36.   B7 j( z1 W+ s4 V( k: P
  37. cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);6 G- Y. q/ p# J9 ~/ a- O

  38. - V  O* v; w# B# K! X- s
  39.    cJSON_AddItemToObject(root, "RobotStatus", subroot);" q* t4 @5 G' @- Z6 h2 R6 G

  40. 9 K/ f; x# P2 Q/ n8 l2 d# \
  41.       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间
    % i/ H* Z8 u. |3 ^3 {  Q( h$ X$ b

  42. " ]. ?+ M: F" x/ u7 c1 Q
  43.       strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量
    + J9 O3 l1 j9 m5 ]+ l9 p: I

  44. 8 c  b7 J1 B6 E  U5 J/ f, X5 ?
  45.       cJSON_Delete(root);//最后将root根节点删除2 L( D+ {5 a; X# x% ~

  46. 6 H7 y5 l% `" i5 m# \% e! }! c/ @
  47.       myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃" @0 e8 [+ g; v* y( N8 [
  48. 7 n3 x# J0 }/ _$ [" @/ T7 }8 c2 m( ?
  49.       return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。. ^  b+ K) f( b% }+ ]& N# r' A
  50. 0 Y4 A% Q5 ?" S+ |7 C5 l2 i
  51. }
复制代码
注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。
  1. #include "malloc.h"
    7 H  P- x" L+ ]% |8 h$ h, c1 a

  2. + P+ F9 R) X# q6 m
  3. //内存池(4字节对齐)
    : ?8 W3 }" r- R& Z
  4. __align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池8 E/ m- R- [8 w* J) o6 U4 A: D1 K
  5. //内存管理表
    ' X- [' S& D: a$ Y* i
  6. u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP
    & G3 N- j& K# b" a! R
  7. //内存管理参数
    + e+ d$ f3 y+ Z/ v
  8. const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小
    5 }" c- ^$ Q2 j$ p1 U# R
  9. const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小4 ?. R9 D& X9 J. l# \; z
  10. const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小
    4 p/ f0 |' A8 q) u; e6 Q  w
  11. + h" J' X0 b# ?0 l+ l. @" ?

  12. - c4 }! I* B8 e# s8 _& R
  13. //内存管理控制器2 ^; o$ g" e8 V* P- X$ T$ [
  14. struct _m_mallco_dev mallco_dev=
    # t/ [; ^5 {1 p: V
  15. {; T/ E! j2 n3 _; b1 N7 U4 G: q" S: M$ G! S
  16.     mem_init,                //内存初始化; J  u- @5 [/ u, M, S
  17.     mem_perused,      //内存使用率% i* n$ Q, y5 g/ ]4 t& C" E
  18.     membase,            //内存池
    + O7 J$ _6 Q/ m! H/ v5 ^
  19.     memmapbase,     //内存管理状态表# y2 I) ^/ l6 C  X8 E& ]* [5 P' d
  20.     0,                        //内存管理未就绪/ O6 z  `' Z0 A1 S1 `/ Q+ p/ M% G8 w
  21. };3 V/ |( a6 `4 X/ Z/ G

  22. % T$ T9 Z/ k0 w+ V! D4 [. K
  23. //复制内存
      y: V1 N4 j) i3 |
  24. //*des:目的地址
    1 g1 X& u6 Q! N6 [
  25. //*src:源地址* Q! V6 `& D! p3 Y
  26. //n:需要复制的内存长度(字节为单位)% y( j" c3 k9 y* I
  27. void mymemcpy(void *des,void *src,u32 n)8 U5 f  o8 w% C7 W1 v6 @( N( q
  28. {! b- m$ E9 K: g9 I+ Q9 A5 T6 Q
  29.   u8 *xdes=des;
    8 m& e; J. s3 v" t
  30.     u8 *xsrc=src;
    8 d5 J/ b( a* X( U1 f, k& _
  31.   while(n--)*xdes++=*xsrc++;* v2 I# s/ [5 _1 _- }. k3 b
  32. }
    7 x/ J% i$ p$ X) ^. u- T
  33. ! A" w+ N. n% n9 X' R) J# c1 G
  34. //设置内存
    0 T# M  I) |! ]1 S; \* j( U& E5 W
  35. //*s:内存首地址5 q( Z+ X- E9 p1 s- H
  36. //c :要设置的值
    ) s2 C. s& d8 @
  37. //count:需要设置的内存大小(字节为单位)4 R) X" C% S5 Q; p
  38. void mymemset(void *s,u8 c,u32 count)' H8 }: `; \4 S; u6 o6 H& s6 v
  39. {
    : V# f! w% y5 S% r& a  v# g
  40.     u8 *xs = s;
    2 X: Y) D5 c* I& y( i5 Q
  41.     while(count--)*xs++=c;
      k' s- b( X* q9 @+ m
  42. }/ {4 |% B1 b+ }8 d! D- ~

  43. $ {$ \$ a  h( k* F" v
  44. //内存管理初始化& J% A* a3 G. _9 x
  45. //memx:所属内存块
    $ y$ U* \2 ^/ `9 G
  46. void mem_init(void)4 U3 _, V5 B" x2 l% K: U! s, x
  47. {. ?. \: I, K& x
  48.   mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零" J4 F1 D  D" R, K
  49.     mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零( e( ?  Z+ {- R- }4 r: G/ {
  50.     mallco_dev.memrdy=1;                                //内存管理初始化OK
    # B# D' u' o. _
  51. }
      L2 w4 ^0 Q& i8 I+ C
  52. $ T1 b) ]9 e/ w0 h2 c, k
  53. //获取内存使用率, S# w# u* M6 P6 t: u
  54. //memx:所属内存块
    5 b1 A% A8 V" X. Y! g  q/ k# _/ \
  55. //返回值:使用率(0~100)
    % p/ B( n! h. X& E3 X3 x
  56. u8 mem_perused(void); L* K& [3 D! A! Q/ g
  57. {
    9 _$ p4 k. o/ c
  58.     u32 used=0;+ a" b  K* t& o/ I0 ~
  59.     u32 i;
    & U$ I. L3 z' y. {) S9 R
  60.     for(i=0;i<memtblsize;i++)/ y8 ]9 b# W) e3 N
  61.     {: {8 {$ n6 Z' j7 I+ U! ?
  62.         if(mallco_dev.memmap[i])used++;1 \9 K3 d3 N3 ~! g
  63.     }# n3 t0 ^7 ~' ]" Y) i! \) h  A# ?
  64.     return (used*100)/(memtblsize);, m' Z6 F9 ]( \: J: L4 N- r0 _
  65. }9 B- d$ e" R" t" \7 f
  66. ) W7 K, n  u% j
  67. //内存分配(内部调用)
    ) h, v1 X" ^* p
  68. //memx:所属内存块4 I4 }5 V0 r2 R9 ~  g6 o# j
  69. //size:要分配的内存大小(字节)9 [% s  G: [% [0 K2 [/ o" J: O
  70. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
    5 v+ h1 Q. E) P; h
  71. u32 mem_malloc(u32 size)4 ~; \/ L; ~0 Y3 n7 O' E3 r
  72. {0 S* Z0 I( }# j# C* _( p$ X# C
  73.     signed long offset=0;
    ( ?# i3 |( @2 T) {4 t- \
  74.     u16 nmemb;    //需要的内存块数& m4 [$ ^, n- z9 o
  75.     u16 cmemb=0;//连续空内存块数* }0 U7 z6 N: m4 \0 o
  76.     u32 i;
      `; {" {6 n( I5 b, R  k
  77.     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化
    / P7 t9 d* t3 ]9 ^6 X
  78.     if(size==0)return 0XFFFFFFFF;//不需要分配) S  z0 D! l+ ?  L5 [
  79. . ?1 p1 c2 H" k/ h4 N
  80.     nmemb=size/memblksize;      //获取需要分配的连续内存块数! |2 K' B+ @% F
  81.     if(size%memblksize)nmemb++;( _  t: t9 @- O+ M- f& T
  82.     for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区
    " P9 N% a$ ?3 `* s4 X
  83.     {
    5 z$ D' n' A" ~. h- R( F
  84.         if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加
    * F* L% J; Q$ v2 f
  85.         else cmemb=0;                                //连续内存块清零" l5 ], ?5 X6 H3 ?) b" n1 S% L
  86.         if(cmemb==nmemb)                            //找到了连续nmemb个空内存块
    ; L. J0 ~& l1 B& X2 v
  87.         {9 ~5 O. v: I9 D% n
  88.             for(i=0;i<nmemb;i++)                      //标注内存块非空
    + _2 j2 w; f8 B2 v3 q- b/ ]
  89.             {( `9 ]0 |) H9 J) N2 `+ N2 o
  90.                 mallco_dev.memmap[offset+i]=nmemb;
    ' O8 O' L8 r) C4 m6 w8 X( R
  91.             }
    1 c! e8 h1 a; r+ [' N: N
  92.             return (offset*memblksize);//返回偏移地址  h" b, N1 Q4 V2 z+ X0 m2 a
  93.         }
    # P3 i6 v* {2 X& F/ u
  94.     }
    % L7 J3 `0 }  a( w0 v+ @# `
  95.     return 0XFFFFFFFF;//未找到符合分配条件的内存块5 @- P' W9 c* [
  96. }
    7 [9 l. Y: D/ s7 t$ N
  97. % o1 K" ?+ Z$ m& r- f0 H( n
  98. //释放内存(内部调用)5 ^) c8 X& V, `; R
  99. //memx:所属内存块3 A# N$ ]3 C; W
  100. //offset:内存地址偏移
    8 v# |7 {  f8 T2 ]! h- v* F
  101. //返回值:0,释放成功;1,释放失败;
    ) V! Y  m7 M2 S/ i7 n# j* M
  102. u8 mem_free(u32 offset)
    9 E( y& }  a0 w) y$ R9 s8 |! c
  103. {) d4 h2 d9 i/ u9 x
  104.     int i;/ h# K) g' R3 l& i2 J4 L
  105.     if(!mallco_dev.memrdy)//未初始化,先执行初始化
    0 N9 L1 x( J1 r2 X1 H1 J
  106.     {& x1 P! L4 N6 K& Z: O  q# z/ q
  107.         mallco_dev.init();
    " E6 g$ z# E: Y% o" d0 t0 A/ d
  108.         return 1;//未初始化
    2 `, B4 R0 z- }
  109.     }
    + }& ^+ D' f, i3 n$ n
  110.     if(offset<memsize)//偏移在内存池内.
    ! ]+ f/ z5 p$ x# g3 w5 e
  111.     {; T+ X: Q! |& l2 E
  112.         int index=offset/memblksize;            //偏移所在内存块号码' e5 [' L$ g- {$ r
  113.         int nmemb=mallco_dev.memmap[index];    //内存块数量" g9 X/ C" ^) q6 F+ l
  114.         for(i=0;i<nmemb;i++)                          //内存块清零, V. C1 J. [* K
  115.         {- s: |# ^% \3 w( c$ q
  116.             mallco_dev.memmap[index+i]=0;! h7 Q2 ], N1 G- _5 ]& Q& o3 e
  117.         }
    " e2 U  t2 e5 H. }. O2 Q7 A
  118.         return 0;
    ) X) A& O% L9 @1 T2 x
  119.     }else return 2;//偏移超区了., q( f( A3 t) x7 ?6 j- C* z4 q
  120. }  A0 o% a2 I5 L- h1 n6 Z

  121. - H+ a7 I$ D6 f" P- ?3 K; ?! o
  122. //释放内存(外部调用)( V! P1 R7 e. d; F: _$ w
  123. //memx:所属内存块
    ( V9 b) e) u- i/ P, P7 ~/ g0 O
  124. //ptr:内存首地址5 |5 M2 Q* b, t$ n; s
  125. void myfree(void *ptr)+ |) m1 s/ _3 H3 C8 Z- R
  126. {# u1 v% n3 |4 u2 N% p
  127.     u32 offset;" S: z  Q$ R; c2 o
  128.     if(ptr==NULL)return;//地址为0.: R) U1 `' K* P# m0 I
  129.      offset=(u32)ptr-(u32)mallco_dev.membase;
    : S) `: ^: p9 W/ B
  130.     mem_free(offset);//释放内存
    9 k  d/ {" `$ J( ~4 B
  131. }8 G" q) V+ H3 Q% L5 s
  132. . W' L: y3 G3 P% V+ l
  133. //分配内存(外部调用)) f  o" v7 p% r1 f* O1 L& W  ?
  134. //memx:所属内存块1 \  D+ S8 N: C; @
  135. //size:内存大小(字节)
    9 _6 D& O% g& @5 ?
  136. //返回值:分配到的内存首地址.9 b- C. Z+ V9 |/ P, \9 q
  137. void *mymalloc(u32 size)
    , e3 L  x  s% h& I4 _
  138. {
    3 U) R' Y, @& r5 s; W1 v. [
  139.     u32 offset;
    6 z5 u( ?  ^; x9 ~
  140.     offset=mem_malloc(size);
    # \8 F" j3 E  H! [9 j! w" M0 R
  141.     if(offset==0XFFFFFFFF)return NULL;) V1 e5 ^1 s8 ^8 q3 ^  ?
  142.     else return (void*)((u32)mallco_dev.membase+offset);! n: b2 c- f" ~& H
  143. }
    9 v" L1 o8 [6 H+ j5 v1 O( B/ C" ~8 E" F

  144. : u: f' M& O; Q" x( N8 K3 k$ t
  145. //重新分配内存(外部调用)
    / ~7 i3 ]3 n# D, A/ z
  146. //memx:所属内存块
    ) f1 ]2 p) T+ `4 q  K! _7 G9 R
  147. //*ptr:旧内存首地址
    ) j1 y1 y/ }6 u7 l8 Q
  148. //size:要分配的内存大小(字节)( Z$ M  G2 _" v. e; U6 V
  149. //返回值:新分配到的内存首地址.# g: W5 a: v* [
  150. void *myrealloc(void *ptr,u32 size)
    - M* n( ?1 T: B1 D  D7 a/ l4 F
  151. {
    8 q. t7 x( ?/ w) ~
  152.     u32 offset;( e) K+ B8 e- h1 ]
  153.     offset=mem_malloc(size);
    : ]" u6 [1 q( d7 \2 B, w0 n" Y) k+ O
  154.     if(offset==0XFFFFFFFF)return NULL;. `. {9 M. y2 k' t
  155.     else
    6 R  E- v1 B. z
  156.     {
    8 L2 o4 X. u! B
  157.         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存
    2 i2 F' ?/ c5 c$ \# [& Q3 \& }4 }
  158.         myfree(ptr);                                                        //释放旧内存, [& P, y6 I2 X$ c+ u' T& a7 G
  159.         return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址1 n$ h* b$ I. Q  I6 D
  160.     }
    % i$ ?9 b, u1 M! `6 I
  161. }
复制代码
malloc.h内容如下:
  1. #ifndef __MALLOC_H, ^0 D0 i, V+ \( @0 T" ^
  2. #define __MALLOC_H
    - z+ `. B8 c  M  J
  3. #include "stm32f10x.h"
    8 d1 X  t$ Z  l; G% e' }+ Y
  4. ; |8 r2 X" i' X! i7 C: B/ s9 S" |
  5. #ifndef NULL% w! ]' B! d1 ^. A% j
  6. #define NULL 0
    . @: E3 L& F% x
  7. #endif
    7 Y9 q! }9 n+ C" \! m! ^
  8. ) U/ J: f8 G. N* ^% r) h# X/ {
  9. #define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节
    1 Q0 C8 \  F; p, |
  10. #define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K
    . z+ t% O8 G; t& A2 Z4 T5 f
  11. #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小  ]+ t4 u$ X/ d& I* I# j( U

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

  13. ! [+ p1 y% U8 {3 v7 q1 G
  14.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- E8 f" M* S9 Q' A1 E
  15.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,& f* Z, g& i# l4 l; T8 U+ S9 _
  16.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  g: C+ a0 Q' k# B9 P* m. C
  17.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER! o, e$ e3 T# @- d8 b
  18.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    4 h+ ~4 K" _$ B$ U
  19.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN1 C% w, I4 ]7 I& l: Z, F: D' s( T
  20.   THE SOFTWARE.
    * G: ^' l+ ?1 U% N4 [
  21. */1 ?8 K( q( w# k$ \4 B7 e6 U

  22. 1 T2 ^$ T" R; W* e5 x8 j! f
  23. #ifndef cJSON__h$ K; R. g+ ~8 P$ `: w/ `( b9 g
  24. #define cJSON__h
    , ?7 |. Y! y9 L: M- C+ [! g
  25. ( t& y3 b. ^! v6 ?% q9 r- l; W' @
  26. #include <stddef.h>$ c" l( K8 N7 _1 C* Q" r; `
  27. 8 t7 t, }! i8 a( V' g1 h
  28. #ifdef __cplusplus
    ) q5 X$ S6 l  @) p9 a
  29. extern "C"
    8 M7 o4 D& f8 g% h; g- d
  30. {
    0 C( S& y8 ^* h7 r1 n1 ]
  31. #endif/ y* f. e7 X/ w' \% y  I6 p' `
  32. / I9 {: B9 x" j  `6 K6 b& k
  33. /* cJSON Types: */
    % g; U2 N* v. [% R
  34. #define cJSON_False 0
    ) L: \7 l2 q. k! _& w
  35. #define cJSON_True 14 t1 _# M3 T, ?' B9 F3 V
  36. #define cJSON_NULL 2
    " K% i7 I2 V7 a; g
  37. #define cJSON_Number 3' }! t" i: e2 Q% p9 f+ G9 m
  38. #define cJSON_String 4
    : \; N0 Y3 w! p  k% t  Z2 P
  39. #define cJSON_Array 5
    7 m1 R9 N, o' O% E
  40. #define cJSON_Object 6
    9 p6 A/ r9 D$ h5 |( Z+ ^( W

  41. ' V7 q* J8 Y; _7 `  N
  42. #define cJSON_IsReference 256
    % }3 _5 `3 |1 A- k
  43. 6 U1 ?! Z, ?' @0 k- ^/ U5 u
  44. /* The cJSON structure: */
    8 u, P' y! J7 u6 E/ @
  45. typedef struct cJSON {
    4 L$ p& H6 \2 t" Q
  46.     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    3 h; {( O8 n9 T
  47.     struct cJSON *child;        /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    ' }1 h( x  U- L9 }5 `3 m
  48. : \' g1 i) t; E0 n0 @3 `. C
  49.     int type;                    /* The type of the item, as above. */( E0 g/ i- |! o; s" W

  50. ; X# Q# S/ k" i4 Y2 d% a
  51.     char *valuestring;            /* The item's string, if type==cJSON_String */
    9 c  l$ H  @2 S. o  t6 i
  52.     int valueint;                /* The item's number, if type==cJSON_Number */
    7 l7 O5 V7 u! X% e. q; @
  53.     double valuedouble;            /* The item's number, if type==cJSON_Number */# |0 g; `/ U. W4 l
  54. " G! Q' N$ L8 _4 K! }
  55.     char *string;                /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */3 e8 }$ Y7 H$ V" S" Z& Z
  56. } cJSON;
    ! }* G) y6 l8 N  u$ _4 T, E

  57. * |* W+ q, u, x1 c1 Q* a8 f
  58. ! z( r) [& d# s
  59. 0 s% ?' P* P7 O5 h
  60. typedef struct cJSON_Hooks {
    8 \3 A( k! b: i7 ], l# r
  61.       void *(*malloc_fn)(size_t sz);0 `7 E) _+ e* G, W
  62.       void (*free_fn)(void *ptr);
    8 h! {& C- F0 ^
  63. } cJSON_Hooks;) H* I3 ^$ q1 R! }) D" T! `

  64. 1 O# L: Y: H, n$ }5 z& Z
  65. /* Supply malloc, realloc and free functions to cJSON */$ T& N. Y9 J' F
  66. extern void cJSON_InitHooks(cJSON_Hooks* hooks);
    - [1 b& o7 i# \% J2 a* V+ S

  67.   Z6 J5 m$ _2 `' r8 p

  68. - a1 F5 d% D; N* d
  69. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
    ' f5 {9 R. z4 N  s9 c
  70. extern cJSON *cJSON_Parse(const char *value);, z7 r' z  h% a. r- O: F" X# a% g
  71. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */, J: e: o4 g' p# t) @
  72. extern char  *cJSON_Print(cJSON *item);. d+ R" @0 j$ u. f  f
  73. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */& L6 Q( {9 a* B$ i8 `* Z) ^/ A
  74. extern char  *cJSON_PrintUnformatted(cJSON *item);
    . V: E& P$ [$ w* N4 Y
  75. /* Delete a cJSON entity and all subentities. */( Z( M/ t* O" O8 p. i3 z7 i
  76. extern void   cJSON_Delete(cJSON *c);
    . J' q: E+ G, \, R  ^- t
  77. 9 s: H6 p6 R. P; b9 @' x1 M8 r
  78. /* Returns the number of items in an array (or object). */
    . D6 ~+ D$ w! O# y# {* K
  79. extern int      cJSON_GetArraySize(cJSON *array);
    ! `( D1 P- T! l$ I: g
  80. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
    ' ~2 E3 r) n( S& l$ b
  81. extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);+ O( i* y  K) p$ O+ U
  82. /* Get item "string" from object. Case insensitive. */1 O) r7 U$ [# ~* x" H
  83. extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    8 U- N& N6 Z: T* T
  84. * ?, V" k& P  @6 Y  S4 D  R) \
  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. */
    2 c9 s& o$ }7 T4 `: k" D. T
  86. extern const char *cJSON_GetErrorPtr(void);
    ( S. w+ _. n4 N  U5 E3 ]+ y/ u# L/ B
  87. ) [, N8 c4 c+ @5 b( l1 w+ K8 b) Y
  88. /* These calls create a cJSON item of the appropriate type. *// v3 F0 q. Q4 G' J6 B
  89. extern cJSON *cJSON_CreateNull(void);
    ' F7 u* @4 T& x1 p& `2 }8 `4 t
  90. extern cJSON *cJSON_CreateTrue(void);
    ; K% N* q  {, I; B
  91. extern cJSON *cJSON_CreateFalse(void);
      \( Y8 I3 s% R5 T& c& Q/ Q
  92. extern cJSON *cJSON_CreateBool(int b);* L; [- s0 w) m' X; `
  93. extern cJSON *cJSON_CreateNumber(double num);6 X; u5 Y) _+ ^7 b6 ]9 _# G; h5 `
  94. extern cJSON *cJSON_CreateString(const char *string);5 M: p# T, G2 \
  95. extern cJSON *cJSON_CreateArray(void);' g1 p8 q0 `; N+ e, o
  96. extern cJSON *cJSON_CreateObject(void);7 A- f- Q, r$ {" K
  97. 7 K+ R6 V6 H1 C' E
  98. /* These utilities create an Array of count items. */" R5 u+ U4 U! z, a; d0 }
  99. extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
    ; I( d  d( C4 R8 G
  100. extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);) w, W( ?+ z! E: U/ z" p: W2 Q  ?
  101. extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
    ( f2 I, v& M- |  _/ ^& D/ {
  102. extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
    $ \/ D( a$ N) ^$ \7 O3 X- |
  103.   ?! S2 J8 G, V0 m; T
  104. /* Append item to the specified array/object. */8 h+ {3 j7 ^* w3 N. `6 x
  105. extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
    / y: o5 |8 N" l( [( u
  106. extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
    9 _6 U9 K1 z% L: r' m
  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. */% w8 ]" ^* }+ w  C3 P6 S2 ~
  108. extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    . B0 r* S) p/ A( q+ c
  109. extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);6 b( g- o$ u- e3 p1 M, E" h9 \- ~$ u
  110. : Q% ^8 C# p& \) W" h8 ^6 l/ @) R) I" ?
  111. /* Remove/Detatch items from Arrays/Objects. */
    4 R' g. [! n  `; C3 C* L2 s
  112. extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
    / V- b- r" X9 R  R6 L7 m, \* z
  113. extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
    6 z1 M- d* {0 e5 ]3 w) Q0 }6 V1 o
  114. extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
    + ?$ T- K8 S8 ~8 m3 [
  115. extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
    3 B* o9 x2 }- H- v! [9 f

  116. 2 R$ R9 {2 n' S# C9 E: i' o
  117. /* Update array items. */
    ) z5 S% n/ D# e! G4 q! ?/ g* k
  118. extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);4 J2 r5 p6 \+ g" k; b$ ?0 Z
  119. extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
    : R# c/ ]' a3 F
  120. $ v1 B( m/ j) }2 ]: I  n
  121. /* Duplicate a cJSON item */
    + F  s* n8 d+ O& N6 S- J
  122. extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
    9 T) W' @# G: C3 ~0 d4 \
  123. /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
    9 g' w" X- ?$ I! e: p7 D6 v
  124. need to be released. With recurse!=0, it will duplicate any children connected to the item.
    0 ~# b- f# q, J/ {/ e, O/ F
  125. The item->next and ->prev pointers are always zero on return from Duplicate. */
    5 @6 T! Q6 D: `; \. X  n
  126. 2 i* m$ n5 N5 o/ g- j4 F
  127. /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
    ! U# v3 P0 |. q) `# o! w7 R- I
  128. extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);; R1 B9 c. H0 L& o  O$ i; t
  129. / W. X5 d$ b& L7 P9 i' r7 c( G3 j
  130. extern void cJSON_Minify(char *json);
    0 [/ g- i) P7 r1 @. j. {; o
  131. $ S/ ^6 o: j1 d5 _
  132. /* Macros for creating things quickly. */
      M% k: J( K) E6 z; |- {# ~. O. L
  133. #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())6 X" m9 e' x5 {  x6 N+ h4 J4 x
  134. #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())9 k7 h( v. @: s8 T  P3 I. v1 U* P
  135. #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())7 U* Q* L9 s! W
  136. #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))- O* B- x) s7 j$ O7 s1 S
  137. #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
    4 S$ w9 G( i0 x
  138. #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))) c+ u1 q4 u4 v& `
  139. 6 N  E7 R2 X" U& @
  140. /* When assigning an integer value, it needs to be propagated to valuedouble too. */; E/ u9 p& f" c5 d
  141. #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
    $ Z( t; ?! i; I4 _% z1 {0 x3 Q8 }

  142. ( R/ U$ v$ F" {2 c; `' t
  143. #ifdef __cplusplus7 Q) W8 {- K3 D+ ^( W/ }3 _: \
  144. }
    + q3 O; q# e9 ~! K2 z& I7 t
  145. #endif( U% p, K: S: b2 b2 V

  146. : O3 }9 N1 Q) y& @  a
  147. #endif
复制代码
下面是JSON数据的解析部分,简单说来就是对号入座。
  1. /**************************************************************************# d: E8 ~4 c+ U+ t2 f/ V3 a+ ^' K
  2. 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令
    & T2 c3 _4 b* r/ K7 Z1 V: E! Y0 R
  3. 入口参数:JSON格式的字符串,
    ' Y1 H# i: \. H" [- d
  4. 返回  值:指令类型7 o- i/ z" M# \! P' @6 c; ]
  5. 注    意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数
    & Q+ }/ v& R4 {. S$ d4 j
  6. **************************************************************************/
    3 [2 U1 Z* K' b) ~- q1 H% N
  7. CommandType GetCommandFromServer(char * JsonDataFromSocket)' a" }7 |) a  n+ G" |: q- ]# O( ~
  8. {3 Y6 C& ?) E! K. t: v

  9. ' y8 M; }% @& _' s5 C! y- |- {
  10. //  ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替
      v3 n" r7 i. k
  11. , {+ h, M) `. x- ^1 G' H# k) F
  12. //    Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替
    7 z: J9 v( q; v
  13.     CommandType cmdtype;0 J- }+ Q3 p# C
  14.   RobotJSON_CMD_TypeDef json_cmd;- i3 |+ t: S* P8 L
  15.     HelloJSON_Ack_TypeDef json_ack;
    7 a6 E" [* S) v* Y( ]6 l
  16. 4 x+ q2 @# V+ i
  17.   cJSON *root,*command_root;( D9 V4 o% C. v$ i3 q1 ?

  18. ! c4 i3 _! C" o6 v
  19.   root =     cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)
    5 M2 q: h! @9 }# O
  20.     if(!root)
    & V4 B8 l2 b5 L, y3 K8 \" |( U
  21.             {7 }5 Z( }0 a* J
  22.                  //printf("get cJSON  faild !\n");
      z+ L$ ^: m4 I( b) t( ?" s* M
  23.                 cmdtype=NOCOMMAND;//如果没有,就直接返回0
    4 |: X) _& f  Y3 E2 b
  24.              }  K; ?1 D7 \' g/ L$ O6 v
  25.             else- n4 x! q& [& c' h+ D$ r
  26.                 {% J' C+ Z/ P7 X+ p2 f$ K# d
  27.                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对
    , `* p8 J5 _- E6 z$ k( n
  28.                     if(!command_root)/ q6 o; |( P, p! _1 j$ e
  29.                         {( v+ |. z( V* j/ H
  30.                                 //printf("No RobotCommand !\n");, O3 G$ {3 A+ z0 q7 }
  31. ' Y& R  I0 C% R- }# a0 ~- x
  32.                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对
    $ m9 s# U3 q; e" S& w
  33.                                     if(!command_root)
    * o/ t% ?, }: p+ c8 M# H8 l
  34.                                     {
    " M" J2 k/ m( a/ R2 }3 ^7 ?
  35.                                          //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回0
    # i& M& i) I( B; I; q
  36.                                              cmdtype=NOCOMMAND;//如果没有,就直接返回0/ k8 C5 }! R. n2 U) b7 {6 E
  37.                                     }6 d* b" U# ]6 M5 E: [4 e
  38.                                     else{5 S/ o" S# X8 E) t" c7 d
  39. 8 s( ]6 Q. z6 m8 @% }4 r. G7 r
  40. 9 F9 S5 S. g5 J$ a3 Q8 r
  41.                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
    / j8 }+ V6 n  z1 x9 B# [. S* T
  42.                                             if(!json_ack.ID)
    + L! P. E9 k0 N+ f
  43.                                                 {
    - U- a2 t5 W% L8 Q8 ~0 }' d5 C
  44.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0% G7 S/ ^" f& [
  45.                                                 }
    4 Z( ~3 f! }7 b4 i
  46.                                             else
    + @% b# d3 a. R! V& H' q6 J
  47.                                                 {
    9 c* B- [! v! H/ k( ]$ T8 F
  48.                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);
    $ L" c. f% m; A+ U4 j$ D) u; J, W
  49.                                                 }
    . t2 X, F& Z5 w9 e6 H/ K* a
  50.                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");1 k3 y+ l7 ~  ~( b0 J# d
  51.                                             if(!json_ack.Time)& t  a( g1 M% H5 L5 d3 Z
  52.                                                 {
    8 N. Y) {$ W3 N6 `5 k3 N
  53.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    & e0 u- E( v3 N" x3 w- t: g/ ^
  54.                                                 }  m( W6 R7 y2 m1 m. t; D
  55.                                             else
    5 g8 ]( Z5 ~7 p# g
  56.                                                 {8 V- u1 }+ r$ G, T; p1 W2 n
  57.                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);
    $ i/ T1 o+ |, |$ M
  58.                                                 }1 K4 t5 Z* P" ^8 j7 i# X8 N
  59. 3 v  _+ z$ m# k' S% T
  60.                                                 cmdtype=HELLO_ACK;//如果没有,就直接返回07 y" Y; T( `- U$ z
  61.                                     }4 T0 a5 L! s- S$ B2 L& S6 n# S
  62.                         }, y+ ?$ \  v2 e3 x
  63.                     else
    % a" _" k6 o! k' c1 G, l
  64.                         {" \5 z9 K. \8 A2 C

  65. 0 j* N+ B/ @7 Z" S1 \* a0 v
  66.                             //运动命令1 k1 T/ a' w5 C2 k: f  O
  67.                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");/ f) O4 V- t2 @4 E4 h) R
  68.                             if(!json_cmd.Command)9 l5 e: d7 r3 Q8 c
  69.                                 {
    2 p/ A$ ^2 `4 H$ \+ `3 k0 X) o6 f
  70.                                     //printf("no Command!\n");- j( x7 J& t) I! W8 ]4 ~1 N" J: m
  71.                                         //cmdtype=NOCOMMAND;//如果没有,就直接返回00 Z" L; W! _0 V" e
  72.                                 }4 u- Y, u0 _( V6 M' O- B
  73.                             else+ \: Q: _- y6 M! R6 K% Z9 R8 |
  74.                                 {$ E( x# o: K6 t
  75.                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);
    4 i8 D: e. M' u
  76.                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);- [% V" W4 J9 H! r% R$ [3 w4 E+ m
  77.                                     //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议
    9 r: V6 w+ d: r$ v' h7 {5 b

  78. + z  T0 Q. r' u$ n/ y) L9 U6 Y1 p
  79.                                 }
    7 e; K$ G4 _9 a9 X; f) l1 A
  80.                             //速度指令7 m/ f. X7 [/ e# J1 C6 X" F- F- S
  81.                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");. p' s- J+ o5 d9 j9 I3 _$ L) V; N
  82.                             if(!json_cmd.Speed)7 ?* [. h: C1 g) I7 p
  83.                                 {
    % E$ I" Z) M7 p8 [3 ~* S% M0 |
  84.                                     //printf("no Speed!\n");7 t" j* E( O  [7 I# l6 s
  85. //                                    cmdtype=NOCOMMAND;//如果没有,就直接返回01 L$ v+ [! E; g+ s3 p' t
  86.                                 }
    $ Q$ [; \+ O8 j7 P9 P: [) p& d3 {3 s
  87.                             else, |  C* |8 K, f) `! l1 p
  88.                                 {% T$ F) |9 U' ]
  89.                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);2 m2 t- B* w2 S: z) X, _& Y$ m
  90.                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;
    ! \0 O! j) m2 P$ \# f5 M+ ~) M' H
  91.                                 }
    1 M- Y& K% N! a. N
  92. $ X: ]. x1 I) v* y8 M% z
  93.                                 //运行次数9 z) \/ e% g; g- I' T1 X" J
  94.                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");3 @; p+ ?  y8 n1 _  x) U+ m4 u: a
  95.                             if(!json_cmd.RunCount)  z0 W# e1 Z$ J( k4 U  _/ G; f
  96.                                 {& @* o5 N1 u8 r5 n) B
  97.                                     //printf("no RunCount!\n");
    8 s% n' ^: g) z1 `5 `
  98. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0/ [6 ?- t4 }$ [1 _  I
  99.                                 }4 {* p4 V# h9 _) Y# w
  100.                             else
    3 ~- f7 g) E8 w; C$ N' C
  101.                                 {+ F$ Y& O( i4 J6 ~2 f7 o
  102.                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);
    ! r9 Y5 W, E: Z  g
  103.                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;
    # [! t0 K  y6 t! ~
  104.                                 }) X2 c$ l9 _. P8 {, D$ a
  105.                                 //开始位置
    + b6 l$ t6 X: g* ~* b
  106.                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");! X5 B" W7 y& A5 M9 J& N
  107.                             if(!json_cmd.StartPosition)
    - [& b- g. a4 P( h7 i& }: U" u
  108.                                 {$ D0 m0 g/ A, \: ?" C( h
  109.                                     //printf("no StartPosition!\n");
      [/ e7 [$ ~. T& ^1 c8 z. G
  110. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回09 A5 j: g- A" |( b
  111.                                 }
    % J4 U$ w. a" H  V6 B, u
  112.                             else
    $ H4 s( _* W+ N
  113.                                 {
    ) A6 n# M) T2 O& J0 E
  114.                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);
    ) B/ {  H: g1 u) V3 C& G$ j
  115.                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
    3 I. q+ f: U) w& F; i+ ~7 ?8 J1 u
  116.                                 }
    + t$ O; r# I" j
  117.                                 //结束位置7 `/ a9 p+ a- z/ r
  118.                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");
    " C2 {) P6 Q$ }; b7 e6 C
  119.                             if(!json_cmd.EndPosition)# e) X0 o- l, Y' H- I
  120.                                 {" L, ]- A0 T  U3 J4 h, b6 O* }# \
  121.                                     //printf("no EndPosition!\n");* t) G' E/ o! C
  122. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0# N1 K0 k3 J/ w& `
  123.                                 }6 d; a; Z- v+ Q1 T2 N0 U$ |' |' A
  124.                             else
    0 c$ B) w9 C3 |: \9 d
  125.                                 {
    $ V/ o9 t+ j+ }6 @+ N, A' _
  126.                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);
    6 F6 P& o" ?# @$ X6 E' r  \+ r# F
  127.                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
    % j& W( P( _1 F: P3 e6 N
  128.                                 }5 g$ s; ~& `. m# _5 q7 J
  129.                                 //目标位置TargetPosition7 ?5 n, b: x- d& m; N. _% K
  130.                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");
    3 ]7 ^/ P) `  ~' q+ j; |- B. z
  131.                             if(!json_cmd.TargetPosition)* l4 b0 `7 e" e
  132.                                 {, ?# [) I8 }$ M8 A
  133.                                     //printf("no TargetPosition!\n");
    6 U- M; g2 q5 E+ i0 O
  134. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    2 }3 c3 z( V% j$ s* I( ^! q
  135.                                 }
    3 C: Q* K& C" v
  136.                             else( k! u/ ?3 h: D. B$ w' R* ~3 z6 O5 k
  137.                                 {
    6 Q! G/ y- J7 f( J. T
  138.                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);! O- n! r) x5 b3 y/ P! T
  139.                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
    4 M8 `+ s- T$ `7 a
  140.                                 }
    3 H' @1 d" }  i% l3 z& U

  141. ( ]+ G  o$ c, \% s$ @# |7 K! I' F
  142.                                 //*工作模式WorkMode;
    5 t$ F& k, a: W, ~
  143.                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");
    9 {) D8 r2 r3 w7 h; ?& W* c0 d& R
  144.                                 if(!json_cmd.WorkMode)* }/ N" e* b; T) t9 Q
  145.                                 {
    4 F* w; ]  G2 A0 v
  146.                                     //printf("no WorkMode!\n");% z3 m2 B  Q& u& s
  147. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0: Q& S% G3 q/ `
  148.                                 }
    * C8 k7 w; v" B1 `% j9 q7 d
  149.                             else
    * y, Y4 V  I2 C, B6 V& u
  150.                                 {
    3 O: e0 P3 B( y! I8 Q
  151.                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);
    $ x" R" a. I9 u+ t% Q9 x) Z( p
  152.                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);: O9 g8 h) \" [
  153.                                 }
    % U% `8 a, p- m- C8 I
  154.                                 //step, o9 U7 ?% r$ y9 i$ Y( ]4 `
  155.                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");. `# @( v& w: w; [* E1 `1 m
  156.                                 if(!json_cmd.Step)
    4 }6 P$ V' F4 e0 S8 x' I
  157.                                 {
    7 c, I2 J' c. R& q& j0 R. C
  158.                                     //printf("no Step!\n");- d8 b1 S/ [& u/ v6 ~
  159. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    $ D7 M/ s6 {( |. g9 f
  160.                                 }
    % P! n1 ^; l$ ^, V! a. u" f
  161.                             else# z8 p+ D; }: ]0 ]% G9 X
  162.                                 {
    , Q/ H9 _0 B9 Z  b" Q# u4 ]
  163.                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
    5 I8 q) [% i7 `, R) k
  164.                                             Cmd_From_Server.Step=json_cmd.Step->valueint;& L# ?+ }' p& g. k% ?! d
  165.                                 }7 u. X& k' {& T6 B$ L% A

  166. ) s2 y$ [" E; w7 K( F# g7 |

  167. 7 Z# T' \% U+ l- X/ V- i
  168.                                 cmdtype= COMMAND;
    6 W6 F9 m4 n, Y0 o

  169. ( T+ @5 H6 {6 |9 J
  170.                         }
    3 h6 r2 [! ]8 w9 `" u1 ]
  171.              }$ g$ Q- R' S* F) M9 s9 H. X

  172. 7 C( u' e5 {7 y8 O
  173. cJSON_Delete(root);
    # |0 _4 t1 J! L$ H& z7 F2 N
  174. $ a" Q, M/ z& U1 k6 Z2 i
  175. return cmdtype;5 o9 W9 H$ A1 _! [- Z
  176. }
复制代码
& j" B' t1 ?- l5 a; }7 p

0 ^, i  F" f; A. L: y
收藏 评论0 发布时间:2022-1-28 19:01

举报

0个回答

所属标签

相似分享

官网相关资源

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