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

【经验分享】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字符串
    & U6 r6 \  |* `9 R: U  v
  2. ; `8 F8 o/ N# }- L+ H8 x
  3. {- I5 f; d5 }& a
  4. : z+ ^3 ^9 m' s% Z* o) U- d
  5.       char *result;
    0 p8 L0 R! H/ q6 \$ v5 `

  6. % G* K1 g% ~; [
  7.       cJSON *root,*subroot;//新建两个cJSON的对象指针
    6 R% q6 [- Q9 M! V4 T

  8. 2 h4 f5 h9 }' E$ n
  9.       root=cJSON_CreateObject();//创建一个机器人状态的JSON对象
    . u1 v; n6 \2 \2 v; m8 r

  10. , x3 @$ u7 i! n- h4 e
  11.       subroot=cJSON_CreateObject();//subroot是下面的一个嵌入对象' s7 Z/ t3 @1 z% K

  12.   {  p1 Y) C: }% H
  13.       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//将status.RunStatus的值赋值到subroot下面一个叫RunStatus的变量。3 ^; F1 \$ G+ u/ j; }

  14. 0 r* {) }. S! n9 x% G& z) J  p
  15.       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);" G4 ^- x  G" B* k8 z* {5 t

  16. 0 c: ^, q2 l/ M+ P# v0 C8 y; i2 s: @
  17. //同上- G3 `( W0 N1 S5 b

  18. , l, u* ]8 a9 y: P: f
  19.   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);3 m3 ?( J" n/ u
  20. ' G# p, S% D8 P5 F8 V1 G9 }3 f
  21. //将位置信息赋值到subroot下面一个叫CurrentPosition的变量,注意此处为Number类型# f- D/ a9 W2 {" W+ P  B
  22. ' C7 ~% M; D* n" l- q2 u2 V
  23.       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);# T/ Y/ a# A4 [# h- k2 A4 O* z  A
  24. ) L  U5 V8 R+ A
  25.       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);$ C. c! x- X: v9 q

  26. * C# M' |9 B% j
  27.       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);  \1 [8 r5 }& [6 h

  28. / h9 ~8 l8 Q# K. O7 Y" P
  29.      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);
      d$ j( C, b  b. _; T

  30. 4 L& ]" q0 r: V3 Q2 ?5 T! P
  31.       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);6 }6 z, ^4 W* H1 c8 [3 K2 a' f
  32. * l, f/ U, X# r: j* j' u. m
  33.       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);3 r: g& o( C" R& w8 S4 \
  34.   r7 E5 e8 I+ k+ s6 {4 b) u8 Q
  35. cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);
    & _1 E4 ^- K5 w
  36. $ ]' Y, g; D4 d1 p/ B/ B3 V
  37. cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);
    7 H8 y# @3 o2 a) K5 d( h3 n. a9 d; C
  38. 0 j) p+ y" H5 ]  i9 ?- D% C( f
  39.    cJSON_AddItemToObject(root, "RobotStatus", subroot);
    + t+ e1 f# [# H( w/ J

  40. . ]0 q5 ]% H/ H9 o
  41.       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一点,就是有点占用存储空间- c, J9 b( y3 `
  42. 2 F1 V- Y2 T, h+ z* Q0 c' f" c
  43.       strcpy(cJSONROOM,result);//将转换的结果字符串赋值给传入的全局变量
    $ S4 g" K) M7 ?) A

  44. % j6 J$ ~* Z' `
  45.       cJSON_Delete(root);//最后将root根节点删除
    , O# q4 M, k4 A

  46. % j* J0 r" M# k7 |% A' U
  47.       myfree(result);//释放result的空间,必须要有,要不然内存里会失去一段空间,最后系统崩溃
    ! b; l. e% T5 N7 C5 D
  48. 8 d/ @  n3 f( e' y2 Z4 [( w4 u7 ~
  49.       return cJSONROOM;//不要指望着返回一个局部变量的地址,这是非常危险的,因为函数调用完毕后这个地址指向的内容就消失了。所以这个函数在设计的时候返回了一个全局变量的地址。
    9 A( X$ u! A0 N4 d6 E( c$ E

  50. - w; l" W9 |" v) D( d5 Y1 S( Z- j' X
  51. }
复制代码
注意:malloc在STM32平台上使用的时候需要改动一下,关于内存操作的改动见下面的代码。使用字符数组会提高程序的可靠性,之前一直用字符指针,可能没有用好,中途会挂掉,后来发现提前建立一个数组,在这段空间进行数据的操作还是比较稳定的。
  1. #include "malloc.h"/ F! E% |2 t8 g8 m
  2. ! h/ W+ }4 K* @9 }+ @& _# U" W
  3. //内存池(4字节对齐)
    1 Q0 f6 B' ]  w. Q& h# a. z/ s- _! O
  4. __align(4) u8 membase[MEM_MAX_SIZE];                                                    //内部SRAM内存池
    & d1 L0 I) r0 I4 j+ y7 l% F
  5. //内存管理表! a4 S0 J* T+ X/ `4 U# a0 ]0 L
  6. u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //内部SRAM内存池MAP
    * y* z1 S* i( P! P* b3 L
  7. //内存管理参数0 J3 d1 }0 D2 f0 A3 s! A4 S! m: \2 m
  8. const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //内存表大小% c6 Z! `; h* D* z9 E# ^: s
  9. const u32 memblksize = MEM_BLOCK_SIZE;                    //内存分块大小
    ) y8 F. z" |8 o" l/ Z( a9 v* m8 d
  10. const u32 memsize    = MEM_MAX_SIZE;                            //内存总大小
    ! f4 T; i- n: ]7 r% C

  11. # K0 ^9 B) V, n# \, H
  12. / a- B5 z& R- V3 `/ L9 g! ?* f
  13. //内存管理控制器0 F9 k3 Z" p& `! B
  14. struct _m_mallco_dev mallco_dev=! [* M1 N1 E3 w8 q( t9 h* v
  15. {
    ' m2 k4 ?& h- L6 m/ V0 F4 Z
  16.     mem_init,                //内存初始化4 ]: t) f: q' A7 w8 y* `- r6 Z  T! n
  17.     mem_perused,      //内存使用率
    " [0 _" o9 V) Z6 R1 }- ?7 G
  18.     membase,            //内存池
    6 Q9 D4 g* P8 X) E5 J, _# r# Q
  19.     memmapbase,     //内存管理状态表$ a+ _3 s4 M/ q
  20.     0,                        //内存管理未就绪1 ?# U7 O: N$ c* H3 ]  s  U
  21. };
    - Q7 |+ x4 `. X2 D
  22. : i4 Y4 I7 x+ K) K
  23. //复制内存
    : N( C5 L& @6 L6 p* n5 l7 J' g
  24. //*des:目的地址, G  H" i" _4 Z$ ]+ u+ W
  25. //*src:源地址
    4 J8 z7 A7 V# m/ w
  26. //n:需要复制的内存长度(字节为单位)' I; E' ]4 A: V8 [
  27. void mymemcpy(void *des,void *src,u32 n)
    / _" e; i2 I. d$ O' [
  28. {' I6 K' N9 t! c1 k% [
  29.   u8 *xdes=des;
    + {% x) d1 C1 f/ c8 i
  30.     u8 *xsrc=src;
    & i5 l4 |; v# H$ |
  31.   while(n--)*xdes++=*xsrc++;: ?. p0 e7 g) m
  32. }4 e; ~7 i0 p* e# O! x" h/ V

  33.   ~8 J0 o- r6 N& f& c, d
  34. //设置内存1 u4 D( ~5 h) P
  35. //*s:内存首地址4 X0 @. [, D  J' a/ x3 d! F
  36. //c :要设置的值
    % O: |: A" o* e) o) S: E* \
  37. //count:需要设置的内存大小(字节为单位)
    # a2 C) s. w$ p" R6 Z9 A
  38. void mymemset(void *s,u8 c,u32 count)
    + s1 @: m! |% P( ]* t# ^" R
  39. {5 N" `* d2 B) T% n$ K0 L, O
  40.     u8 *xs = s;. p8 Z. _# Z* C0 o; l. @$ }
  41.     while(count--)*xs++=c;$ s- s' a' E2 W- I+ ~
  42. }; h, s5 I1 F- e4 d7 e  L
  43. ( s  M. B  `9 H: P5 w
  44. //内存管理初始化
    " m8 ~. ^; {8 F- N6 {6 i4 P
  45. //memx:所属内存块
    " Z+ a/ i+ H$ @0 k# e: h
  46. void mem_init(void)6 }1 Q, \. _$ N8 Y( Q' ]/ Y5 |
  47. {/ l$ s0 L& \( `; E2 f  r
  48.   mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零6 ^( m7 S' L2 V1 ?
  49.     mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零
    ( }/ r. ~# b6 m7 S/ ?
  50.     mallco_dev.memrdy=1;                                //内存管理初始化OK+ X" @& `9 x8 l/ N
  51. }9 T# Z2 K8 t, D0 D4 M2 V& W( {

  52. / [& g& E& f, b1 h
  53. //获取内存使用率
    * Z2 Q2 G  o* h4 \: r
  54. //memx:所属内存块/ T. {, @) \5 F0 B
  55. //返回值:使用率(0~100)
    . {4 N3 o$ x) h, M
  56. u8 mem_perused(void)
    * {6 k6 l+ d5 V( R
  57. {) Y" v! j  Y$ v" m+ |( a- ]# G
  58.     u32 used=0;: g: {( P* f' {6 T1 |0 `
  59.     u32 i;
    ' G- t  E# F, p
  60.     for(i=0;i<memtblsize;i++)
    $ r* l+ Z( L! z
  61.     {
    9 c* T: G7 ~+ I$ r* X. @, _$ m2 w  [
  62.         if(mallco_dev.memmap[i])used++;
    9 s' ?0 ~- O) w7 x3 [# x9 k0 [
  63.     }' q2 c) N4 ?# U& R& |2 X; s
  64.     return (used*100)/(memtblsize);  o6 \$ T; v4 S' z
  65. }0 N+ |$ x# p* I

  66. 8 }1 L+ k+ m) u9 ~; R9 Y9 X
  67. //内存分配(内部调用)
    ' F- @  M' s3 |/ a
  68. //memx:所属内存块6 N# y) n5 \/ O; L
  69. //size:要分配的内存大小(字节)( g* p: W) W- k6 q
  70. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
    7 l4 D( D4 A6 H, z# i
  71. u32 mem_malloc(u32 size)
      D. n$ q" l  I) S* ]
  72. {
    ( U3 J8 x2 T! z3 T1 u1 ~- m+ H
  73.     signed long offset=0;$ A  K$ H. Y7 C6 G- P. s& ~
  74.     u16 nmemb;    //需要的内存块数
    / H6 n. v1 \) I3 d6 r/ x& F
  75.     u16 cmemb=0;//连续空内存块数) a$ y0 f& ?  J# g
  76.     u32 i;9 q8 x# q. Z  y* T) \, t5 @9 ~
  77.     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先执行初始化9 O3 \* H* G7 e, a/ A2 k
  78.     if(size==0)return 0XFFFFFFFF;//不需要分配
    6 O  B: x2 \( b; |& r7 B
  79. 8 O* V% |# D, [% e9 ?1 Z* L. l
  80.     nmemb=size/memblksize;      //获取需要分配的连续内存块数
    : N0 m% Z8 |* Y" _; v! n, y9 E3 L
  81.     if(size%memblksize)nmemb++;
    7 A0 q' q* b" {/ w
  82.     for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区2 n, j% p1 l6 b% J8 u
  83.     {. p, n' z3 G' x6 @1 y$ c2 H
  84.         if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加6 g3 |9 w# q3 W7 M
  85.         else cmemb=0;                                //连续内存块清零* Y0 `8 E) `& T! t& Y7 m
  86.         if(cmemb==nmemb)                            //找到了连续nmemb个空内存块0 m7 \' f; F4 G2 B0 J; t
  87.         {- y; C( W9 e7 d- M, \9 L
  88.             for(i=0;i<nmemb;i++)                      //标注内存块非空6 U$ V$ T- E2 A2 ]9 ^" x
  89.             {
    7 C8 Y$ E6 ?9 a) y
  90.                 mallco_dev.memmap[offset+i]=nmemb;
    , f) _) k+ Y- H) \, V
  91.             }. n$ S" x* I% S- Q1 m4 M! {. Z4 k
  92.             return (offset*memblksize);//返回偏移地址( |; @, v# [) k+ x+ D9 K$ l
  93.         }
    - Z/ R1 F. c- ^+ ?" G& ^
  94.     }
    5 W! \1 t, t8 z( V1 @
  95.     return 0XFFFFFFFF;//未找到符合分配条件的内存块5 }7 y, |! z' H6 Q0 V) G
  96. }3 O3 c3 [  J: T6 F
  97. , x% y! |# O; D+ H
  98. //释放内存(内部调用)
    ! I3 ?! {$ O! C* E  h7 Q& s3 @! P
  99. //memx:所属内存块
    ) T- j0 H+ E' D3 D" R, d
  100. //offset:内存地址偏移
    & i$ N5 Z: J  J$ {) i$ L" N+ b$ ~
  101. //返回值:0,释放成功;1,释放失败;3 @& R, Q$ `) W: }1 n
  102. u8 mem_free(u32 offset)
    ; n: ]0 M  R. C
  103. {) y. Y8 i+ @% F, N6 u
  104.     int i;$ `( q1 o4 A# n) H# m3 n: `' K
  105.     if(!mallco_dev.memrdy)//未初始化,先执行初始化+ e  Q3 ]. b8 h( b5 \
  106.     {
    + B& ]* S/ |. r; o% q- A, i6 G
  107.         mallco_dev.init();$ M$ p2 [: |6 y% i
  108.         return 1;//未初始化
    3 G9 x0 T, s3 P( |0 k
  109.     }
    * H& F  I: p, A/ Z( ^5 V* M! z
  110.     if(offset<memsize)//偏移在内存池内.4 G! |6 B' S& g. z, N: l; z( \2 q; [
  111.     {
    5 ?2 c/ N% P- ?2 R
  112.         int index=offset/memblksize;            //偏移所在内存块号码0 N8 |: \8 _. T4 Z- q+ a* y& p
  113.         int nmemb=mallco_dev.memmap[index];    //内存块数量
    0 R# K# f7 U& }8 d1 a% C  T+ {$ G# J
  114.         for(i=0;i<nmemb;i++)                          //内存块清零
    1 d6 w" w  e- z
  115.         {
    4 a2 a2 T5 z8 V* s
  116.             mallco_dev.memmap[index+i]=0;
    % k! I5 T/ _! i* p- T
  117.         }2 o3 I" M8 h. m3 J
  118.         return 0;
    3 F6 t0 J6 p- Y( p2 v  v! `2 s, E
  119.     }else return 2;//偏移超区了.
    0 {4 j9 C+ S& y# N" G3 F/ j
  120. }
      h( K% a! o& ?

  121. 3 ?- X( R# r; E. {
  122. //释放内存(外部调用)+ g! j' R" U3 O. {3 _+ C
  123. //memx:所属内存块# l/ Q* Q" [0 v* h( m6 P
  124. //ptr:内存首地址
    " m  F$ O; @: Y" m* Q
  125. void myfree(void *ptr)$ M4 @& z. O! P& B0 v+ |/ U% c
  126. {
    + u% o* M$ ^) n0 b. t! h0 a! o
  127.     u32 offset;
    4 s( h3 ?, i; E2 v, k5 F4 u
  128.     if(ptr==NULL)return;//地址为0.
    + |  O: E: l, o! G9 w4 X
  129.      offset=(u32)ptr-(u32)mallco_dev.membase;) K- V/ {7 c$ \! Z: G; r
  130.     mem_free(offset);//释放内存" o  \. X) T' A( {, `8 Y% W( [
  131. }8 ^. U* ]* C5 r0 \8 z, H+ U
  132. , T2 Y2 v- v( I/ q
  133. //分配内存(外部调用)% ~5 u- `8 l7 W$ O6 B* R2 c4 P9 I( n
  134. //memx:所属内存块
      X' l- ]2 B; f. a
  135. //size:内存大小(字节)
    3 p6 i2 W, u5 ?8 Y1 o+ N1 c' \
  136. //返回值:分配到的内存首地址.2 T6 N6 m! ?( a
  137. void *mymalloc(u32 size): K4 u) i0 F6 ^- H/ i$ I  z* p
  138. {5 x+ B5 e) L* h$ Q; u
  139.     u32 offset;
    7 M" E  C% |6 C/ {  F
  140.     offset=mem_malloc(size);0 T# P. s5 i8 h, _4 J& T
  141.     if(offset==0XFFFFFFFF)return NULL;
    6 H& \" H! V4 a5 h
  142.     else return (void*)((u32)mallco_dev.membase+offset);
    3 W1 {% |6 X8 |" h, f- |/ T
  143. }
    - j1 f3 H# h' o: l

  144. ! ?! n4 f0 x- Z5 s2 z9 i2 g
  145. //重新分配内存(外部调用); y5 G8 c4 @$ ^* K2 i4 t5 w2 k
  146. //memx:所属内存块* i5 R' l, _2 K$ M7 S3 C
  147. //*ptr:旧内存首地址: ]# {, l$ T0 K  r
  148. //size:要分配的内存大小(字节)( A. I; z* z  p6 f$ o
  149. //返回值:新分配到的内存首地址.
    ' S& v5 f8 Q7 K& b. s; S# y+ Y4 v$ U( m
  150. void *myrealloc(void *ptr,u32 size)
    : J8 E% N  B9 y1 F: S; z6 f
  151. {& |5 P3 y* w* ]1 O$ |
  152.     u32 offset;
    . u0 `* [7 p/ a' d; j& B
  153.     offset=mem_malloc(size);
    5 A+ @) u/ Q  t: r5 A
  154.     if(offset==0XFFFFFFFF)return NULL;4 h. e5 j; q8 |" x
  155.     else
    ) F1 G) z0 W1 A) {: j
  156.     {. ^' P5 U' G0 H( T" @3 w4 g, m; q
  157.         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷贝旧内存内容到新内存( ]5 j' a, L, K( u/ B/ X( A
  158.         myfree(ptr);                                                        //释放旧内存
    8 D: {/ z1 T# ~, y; R# r2 y( {' j
  159.         return (void*)((u32)mallco_dev.membase+offset);                  //返回新内存首地址
    2 z; n  @% g) ^/ ^( V
  160.     }
    . h: u* X' ~6 X+ U# S0 y, u( J
  161. }
复制代码
malloc.h内容如下:
  1. #ifndef __MALLOC_H4 n9 z- [! {5 T% M; F
  2. #define __MALLOC_H
    ' h$ e2 |+ |% z' q1 w  C
  3. #include "stm32f10x.h"
    ) r* |4 n% ?( x

  4. $ E/ k; v+ @% Z: I6 ?* P
  5. #ifndef NULL9 e0 D- t) ^  [8 V' i; ?
  6. #define NULL 09 M: k% g3 l0 d9 Z! l& d
  7. #endif
    ( O$ q6 w! G0 X* `: U2 O7 @
  8.   c: K2 D: n9 u6 J$ k1 W  j$ g
  9. #define MEM_BLOCK_SIZE              32                                      //内存块大小为32字节5 x+ n8 U) f9 V8 w5 k
  10. #define MEM_MAX_SIZE                16*1024                                  //最大管理内存 2K
    + w# b. |6 c5 Y1 V
  11. #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小
    ( o8 S+ \: `; O% c; l
  12. 2 G3 q( U  \5 @% }; }9 R
  13. //内存管理控制器+ H$ R* o2 X  O4 r" Y+ _/ Q7 R
  14. struct _m_mallco_dev
    / z/ Y) Q- S+ Q9 |
  15. {
    , E+ j) n) ~( f8 a8 k( C
  16.     void (*init)(void);                    //初始化( x7 c+ A# }2 J9 I; H4 I
  17.     u8   (*perused)(void);                      //内存使用率$ Y# W$ G) y# K# Q
  18.     u8       *membase;                    //内存池
    8 r2 g7 q$ D7 r* _" C
  19.     u16   *memmap;                     //内存管理状态表
    6 z) n( `+ A  l4 h
  20.     u8     memrdy;                         //内存管理是否就绪
    8 n) ]+ x+ _1 q0 b* L9 D
  21. };
      u% m% m  R9 }8 d3 W

  22. * g2 Q/ n1 s+ ]4 T9 B
  23. extern struct _m_mallco_dev mallco_dev;     //在mallco.c里面定义! q/ l# M/ H, O

  24. , K& f4 W; g$ Q% L* h
  25. void mymemset(void *s,u8 c,u32 count);     //设置内存
    , s" e+ T: Q6 u5 u' F* n! k% x
  26. void mymemcpy(void *des,void *src,u32 n);//复制内存: g% t" r8 B7 a+ s  U7 _) {

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

  10. 8 D6 i1 R2 D% l1 P1 F
  11.   The above copyright notice and this permission notice shall be included in8 X2 F) j! m  \9 g
  12.   all copies or substantial portions of the Software.
    3 ^) M- \6 d' f
  13. * J2 s5 ~' \) N: k
  14.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    $ a* E  \6 n( j  O  S4 _1 ?! S
  15.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    : \, O. u$ R( ~* N
  16.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    % _5 b& l7 ~4 ]! }0 ^
  17.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER) [* [5 x- O; [1 ^: f- O, g
  18.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    * u1 M) T/ p# G8 K5 H/ t
  19.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    + Z- ?/ ~( p; g: l4 `
  20.   THE SOFTWARE.7 ?6 Z( y6 t0 R  u: w$ s- U/ R- L
  21. */
    3 [* ]8 k, b' D
  22. ; }+ v- H0 q. j* B' n! I, K- z
  23. #ifndef cJSON__h
    # U9 |  e" b' o) ]1 X" R
  24. #define cJSON__h3 D: B6 c4 G/ R& }% l2 k

  25. % Q) d) e; m  c7 s: D
  26. #include <stddef.h>- ]2 S; S9 u! Y% x

  27. $ k/ n9 s! w4 G7 k
  28. #ifdef __cplusplus3 l9 O3 Q% C+ y+ R1 y5 y; u: J/ ?7 }
  29. extern "C"
    + e+ M. C' M/ L! ?0 i
  30. {; d0 d9 ]4 c5 |4 B4 m& c& a
  31. #endif
    5 I, \* t2 V2 f9 k- v* ?' t$ a
  32. 4 U5 q" B0 r) c" f( L" t8 D
  33. /* cJSON Types: */
    % ^8 i& ~4 M% P2 ?: R& _& l
  34. #define cJSON_False 0
    1 k8 [6 F9 u! t  A8 E4 G' e& E: b
  35. #define cJSON_True 1
    + A! i  D* w: `7 X9 i2 J7 k
  36. #define cJSON_NULL 2" @( K" |" o0 e# z' F& p5 M
  37. #define cJSON_Number 3! B1 H: q7 `) f  _  C
  38. #define cJSON_String 4$ U% C8 D7 @. l9 J/ z
  39. #define cJSON_Array 5$ |; p5 V" h# r9 E6 L  i
  40. #define cJSON_Object 60 L& C# @9 U0 i. O! I1 e
  41. 1 ^# v4 K* J' g# p1 t0 i
  42. #define cJSON_IsReference 2565 W+ g2 o, Z+ k
  43.   z( X  {4 s; A" i
  44. /* The cJSON structure: */2 r$ V+ @* y: B7 Q% |. M
  45. typedef struct cJSON {
    9 A& D) M6 i  c6 V& X4 h( N
  46.     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    7 C' k9 k6 ^  O% Y' b
  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. */) d3 ~* X% M$ W% z" O

  48. & s  v1 O3 r& U2 w& v* O
  49.     int type;                    /* The type of the item, as above. */
    " H$ a/ K. v* d( t

  50. 2 D3 P: w4 J+ S& r- D/ u
  51.     char *valuestring;            /* The item's string, if type==cJSON_String */4 J- q9 _! M! u: r
  52.     int valueint;                /* The item's number, if type==cJSON_Number */
    ' d4 n5 j/ J+ w/ T# j
  53.     double valuedouble;            /* The item's number, if type==cJSON_Number */
    % D# L# _# u" P2 L

  54. $ l/ n, ?7 I! G$ d- y* |' ]
  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. */+ t; t( ~3 V' M1 N2 F8 z% n
  56. } cJSON;, m% b' b( j! {0 c# H
  57. $ {1 u* C4 ~! ]: e! h
  58. - s4 |2 S6 @& Q$ ?7 P4 l
  59. $ Y$ G) }& m* c! W( U4 p
  60. typedef struct cJSON_Hooks {
    9 W( R  z. r' e+ N
  61.       void *(*malloc_fn)(size_t sz);; o$ r# X$ u, }; }1 C& F% c
  62.       void (*free_fn)(void *ptr);/ k8 p5 O( P. k0 p
  63. } cJSON_Hooks;
    ) M* b7 z' `* Q& R* \: ?

  64. ; C7 f, Q5 {+ V3 a# Y" Y
  65. /* Supply malloc, realloc and free functions to cJSON */& R+ i3 X8 R4 n. |
  66. extern void cJSON_InitHooks(cJSON_Hooks* hooks);0 I% B9 T) t  ^8 C: ?
  67. * ]$ y% O8 I* T; }, A4 _( d9 H

  68. % ^4 v( x: a/ |: A. Q# @2 m) a
  69. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
    ( ?  @8 z6 h7 L6 P8 v1 {$ r  G- C/ @
  70. extern cJSON *cJSON_Parse(const char *value);0 R* a3 R+ i6 \( n( j6 k
  71. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
    0 [/ a& ?8 f/ x. H5 e& v- b
  72. extern char  *cJSON_Print(cJSON *item);
    2 r8 S9 k* k3 o2 |+ @2 [' ~; R/ `
  73. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
    # y) p. T' J% C6 |, H- ~
  74. extern char  *cJSON_PrintUnformatted(cJSON *item);2 u1 [: {& C" H  p% ^
  75. /* Delete a cJSON entity and all subentities. */
    / |$ I  h$ I0 X# Y
  76. extern void   cJSON_Delete(cJSON *c);. c# S3 E- M' ?  c7 S
  77. # q. }' w; L( _8 z# n! h. d( Q2 L
  78. /* Returns the number of items in an array (or object). */9 g  J2 R' H) O( W+ p
  79. extern int      cJSON_GetArraySize(cJSON *array);) G6 o: x; B2 N4 @! E& P$ ~0 ^1 V. k# k! k
  80. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
    0 A* L; K& H: d- j& F( a+ u
  81. extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);8 U9 Y2 Z8 C! N* }( E; e
  82. /* Get item "string" from object. Case insensitive. */) p. T: d% A* T+ ^9 }: a- `- M6 X8 y
  83. extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
    3 v+ g% t6 w# ^

  84. ) k6 A  ]$ B+ J. w
  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. */
    9 d! }7 s" v! v! t
  86. extern const char *cJSON_GetErrorPtr(void);
    , C, a* W$ {4 s( a4 p7 _- F" [
  87. 4 |$ V* {1 t, X" D1 L0 s
  88. /* These calls create a cJSON item of the appropriate type. */. n! Y) U1 }% c9 W1 ~) z3 J5 j
  89. extern cJSON *cJSON_CreateNull(void);
    5 v' ]7 S$ q6 G/ S
  90. extern cJSON *cJSON_CreateTrue(void);
    3 H1 o. B0 e1 R7 o+ V
  91. extern cJSON *cJSON_CreateFalse(void);/ ~& M& `" e2 ~% t, u1 q1 c
  92. extern cJSON *cJSON_CreateBool(int b);
    . u" l! W5 V# a; r1 V
  93. extern cJSON *cJSON_CreateNumber(double num);6 ]! Q% [1 L- @/ J0 z
  94. extern cJSON *cJSON_CreateString(const char *string);
    ; m1 H8 c/ h7 X- T3 X
  95. extern cJSON *cJSON_CreateArray(void);
    6 D3 {( Y: W* p& O% {7 _% z
  96. extern cJSON *cJSON_CreateObject(void);
    3 }. {2 @6 X: {) [5 t
  97. % e0 [$ s8 p! j
  98. /* These utilities create an Array of count items. */# k! m( z+ |9 C' B$ b
  99. extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
    3 L9 P  O, s2 \5 T: M  P/ e+ l
  100. extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
    1 A8 V$ Z! r) v
  101. extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
    ! J2 N4 ^& E3 @" t5 X. r+ \4 y. ^
  102. extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
    6 r$ b# _- ]+ O. j2 z+ U2 [# w6 x

  103. / o- m7 s/ L( i
  104. /* Append item to the specified array/object. */4 }* {  s2 W  U, U
  105. extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
    % B. Q4 Q; P+ x3 s* N  @  R" e
  106. extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
    & o: y2 H1 F8 c  u5 i' F; d
  107. /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */  m: p' {9 f2 J
  108. extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    6 _3 [. B4 ~% c1 c7 ]
  109. extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);- n7 d) ~8 e+ V1 G1 ]

  110. + i# T- m. q5 K; \4 M* q
  111. /* Remove/Detatch items from Arrays/Objects. */- Y, `4 T% L/ w) c. x2 P# X
  112. extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);) a( t& @, H9 d
  113. extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);5 h$ L, V) r% B- m2 y; M: D
  114. extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);9 G& g) q( d! B) D. G$ T) d5 t8 h7 G6 D  ~
  115. extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);. ~  b/ E; B+ l9 \6 u6 x

  116. % s5 Y4 _) t$ k# L  Y' S* E5 X
  117. /* Update array items. */
    . ^$ }' S0 H9 V( J& Y1 o3 B; p% z# i
  118. extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
    " W  ?  R# @5 \' L! l
  119. extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
    3 I0 l9 W3 Z7 j5 Y% e7 H

  120. # {7 ^6 @2 I6 A' D
  121. /* Duplicate a cJSON item */' ]/ H. [+ F; X7 O
  122. extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
    2 x# [$ q/ e, A) r5 u% `* `, z" j! a
  123. /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
    ' A# o) ^/ A& i- l2 d5 e
  124. need to be released. With recurse!=0, it will duplicate any children connected to the item.
    / O$ L! E! ~) z9 l
  125. The item->next and ->prev pointers are always zero on return from Duplicate. */
    * s: y& d/ T% a& x
  126. $ b" h* n1 E; X: X
  127. /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
    + o; w3 m. F; }) z. ?1 Q; u1 d
  128. extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
    9 c6 o) n. ^0 r( r8 Q
  129. + V3 Y2 h8 c3 T% `! c
  130. extern void cJSON_Minify(char *json);5 l* L# v% \1 ]
  131. ( M, C% i; p1 F2 {- {$ z' I
  132. /* Macros for creating things quickly. */1 V* ]1 M* l! d6 T9 S7 A
  133. #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())1 w" ^0 ^. n& q9 o
  134. #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())" n) e) F! {  Y$ i% E( o' l6 D
  135. #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())3 M( n) k: A+ m: @2 m: Q: D: A
  136. #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))& p- [% A& _" S! Q& n9 D+ s, Z
  137. #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))/ D- v  @+ r( {( i- H
  138. #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))9 ^8 A0 l4 Q  d* E6 k2 Z
  139.   z# D* w% N# c
  140. /* When assigning an integer value, it needs to be propagated to valuedouble too. */
    . s( b& e* T1 T1 u4 y: R
  141. #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
    + B' n- u8 I5 N

  142. 0 ]) n5 m$ F# A1 G' R
  143. #ifdef __cplusplus3 }1 |3 w0 s2 \8 @
  144. }
    1 c, Q( A* R) E0 D
  145. #endif
    # w9 [% H  q' @0 n0 G8 q- [
  146. 1 v- @5 N8 b* [; u+ ?, S3 v
  147. #endif
复制代码
下面是JSON数据的解析部分,简单说来就是对号入座。
  1. /**************************************************************************
    4 E- q& l$ [/ n5 q& P$ g
  2. 函数功能:JSON字符串解析,按照命令格式,解析出上位机发送的命令
    " p/ r% @9 G# _
  3. 入口参数:JSON格式的字符串,
    " Y9 O7 l* f. p; G, b' G1 u
  4. 返回  值:指令类型) I" z5 A" K1 C# e
  5. 注    意:从服务器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函数( D5 B  L1 _+ w( d+ T1 w5 G( N
  6. **************************************************************************/! M& ]* M  S! i+ }8 S
  7. CommandType GetCommandFromServer(char * JsonDataFromSocket)
    2 o+ i5 u* P6 q$ y5 d
  8. {
    . z5 E. W; B7 {( d( D  B' Z
  9. " m1 m6 {3 e& J2 u$ }5 I7 Z) S
  10. //  ROBOCmd_TypeDef cmd;//使用的时候用全部结构体代替" ^  M2 n, H6 _3 p

  11. / n+ z. [( T- E# k* R5 \- |/ e; q
  12. //    Hello_Ack_TypeDef hello_ack;//使用的时候用全局接头体代替8 x, i$ P2 d5 R, K, g5 F
  13.     CommandType cmdtype;
    % V% j: c  }' x5 P
  14.   RobotJSON_CMD_TypeDef json_cmd;8 i* ]$ q5 R- u% p# r
  15.     HelloJSON_Ack_TypeDef json_ack;4 t7 l2 T5 k/ k

  16.   n6 P& x0 Z, c5 I: a- C
  17.   cJSON *root,*command_root;" k. g# S5 v$ [, K2 r0 o
  18. ; h8 r0 G& \' v; H  j6 S
  19.   root =     cJSON_Parse(JsonDataFromSocket); //实例化JSON对象(静态对象)
    % ^5 y4 O9 |5 v9 v! A
  20.     if(!root)
    2 p% P8 j: c6 N- B. j, U
  21.             {$ ]. P2 h! U: }; Z
  22.                  //printf("get cJSON  faild !\n");
    & x3 `8 x( V( m4 S2 V9 \+ q) q# m
  23.                 cmdtype=NOCOMMAND;//如果没有,就直接返回0
    0 T* w0 H8 m# `$ h& K- U7 _) F4 j
  24.              }
    % e1 |+ L6 C+ T, P
  25.             else
    , y5 Z* s8 V: l
  26.                 {9 O5 |$ l& u  q6 q' ~. Z
  27.                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand键值对% a9 f& |& |. F4 @  |3 @# M& u
  28.                     if(!command_root)
    * O) S1 J: z; u: Y+ J- B7 G
  29.                         {
    0 P$ U0 I! i# k5 x
  30.                                 //printf("No RobotCommand !\n");
    1 K# _, i9 X" @* E* o/ v3 C
  31. ( G) y9 B5 E7 j3 r$ M; v4 m
  32.                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK键值对/ c. D/ z' M& c+ M, \
  33.                                     if(!command_root)" R4 s. ~9 W4 |9 Y! U6 C) p
  34.                                     {
    5 ^- b% }- ?$ f
  35.                                          //将函数的返回值改下 既不是RobotCommand也不是HelloACK的情况就返回00 ~2 I) I4 p* g' L& Q
  36.                                              cmdtype=NOCOMMAND;//如果没有,就直接返回0% Z) t( O# w4 g9 E- V+ i
  37.                                     }8 G- N" m3 y7 I
  38.                                     else{# Z! [% L9 H( @# u, o

  39. 0 ~( }9 D* O; Q- b1 O! j
  40. % r, a- H' t2 z" Z8 J% I" P
  41.                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
    2 F; M3 ?( g4 Z8 B
  42.                                             if(!json_ack.ID)
    8 R' i) i$ I; j9 Z, G! c( Y
  43.                                                 {' b+ G1 S2 w* o1 f. `
  44.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    - P4 K, y! M$ x- X7 k
  45.                                                 }. B4 J2 I- N/ |# G! {0 v7 n
  46.                                             else
    ) s9 {! @! [" y  ^; \3 }, f
  47.                                                 {7 l: L0 T+ d: j  A3 a
  48.                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);( o# L0 P6 M  Y: c
  49.                                                 }
    6 z0 z/ q! u. |6 S
  50.                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");  Y4 @$ q  ^* |$ C0 l
  51.                                             if(!json_ack.Time)* X; q: L6 r& l
  52.                                                 {
    : c% a* `7 p, o6 N$ B
  53.                                                     cmdtype=NOCOMMAND;//如果没有,就直接返回0
    " ~& X- s( v' ^1 j; k, X
  54.                                                 }9 H: v2 f9 [/ b
  55.                                             else' R+ O$ w( S; @+ {
  56.                                                 {
    4 C0 t: E3 r& j" Q
  57.                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);  H# Z4 ^9 }6 U9 R3 b: e
  58.                                                 }% f" F* ~+ v) @& B. q  t% e& h

  59. 1 ?  B. K) J5 O+ ]1 Z+ Z3 f
  60.                                                 cmdtype=HELLO_ACK;//如果没有,就直接返回0
    . F$ w* g7 h, Q+ E
  61.                                     }* [5 e' G; v) ]7 Q2 c: M0 N
  62.                         }2 ~4 V, \. e# ?% Q1 l6 _
  63.                     else
    2 Q7 Z6 t% u0 z/ d# m0 j+ o
  64.                         {
    4 b0 T( i. [. c3 w7 z& s3 C$ {

  65. # v3 s1 X# K& X# n( L
  66.                             //运动命令0 m) W' Y- A( ~0 e' b* _: q
  67.                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");
    # h4 {2 \: I, D6 j' }6 y( @
  68.                             if(!json_cmd.Command)
    . h# R* L5 y; j/ v9 W, H
  69.                                 {) x6 m4 I! Z$ a3 N
  70.                                     //printf("no Command!\n");
    + w: `6 s) y3 i; b* T" {" ?
  71.                                         //cmdtype=NOCOMMAND;//如果没有,就直接返回0" G' `: ^9 m3 Y2 [+ I
  72.                                 }
    4 X% Y. m3 x1 ~' }( [. J7 C
  73.                             else" S/ f# m$ V& b( k/ N2 r$ K4 d
  74.                                 {
    5 V2 H6 V; q, W; |! X) h+ v0 h
  75.                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);
    * Q- i$ U% q! L8 T
  76.                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);
    - o% q# [; X; u! R
  77.                                     //此时应该发送对应命令的OK程序,Set或者Auto或者。。。具体见协议& f- Q3 D0 e/ V, X# v0 A

  78. 7 X9 x0 H* {6 {+ y% F# h
  79.                                 }
    ; \1 f5 G( R  c$ _0 c1 a
  80.                             //速度指令8 k- \$ ]7 N" S$ J' L+ d1 ]* x
  81.                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");. `3 e2 f* X* h( C7 H
  82.                             if(!json_cmd.Speed)
    + e5 N7 E' V1 |) h8 \# e9 I
  83.                                 {5 n2 `& S7 x$ N1 b0 Y
  84.                                     //printf("no Speed!\n");
    ) s( M) e8 L, b  x: H4 B
  85. //                                    cmdtype=NOCOMMAND;//如果没有,就直接返回0
    # d- M8 |3 f5 E& l
  86.                                 }
    $ l- D; `4 f3 l, `3 ^( n2 A; B
  87.                             else9 t& r, M7 e  s; s; q8 e
  88.                                 {  A5 W1 u. I# L" i  L, |/ ]
  89.                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);* C8 W1 Z% G* ]+ Q: k
  90.                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;1 `* \2 `! p3 ?$ N/ }9 L* f
  91.                                 }* n6 [0 p$ u% G8 Z* D( |9 |
  92. - M- K4 d( r$ ^% V2 B" e
  93.                                 //运行次数
    2 P4 ~" j( k# r+ f7 V
  94.                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");
      q& s! H# M! l* T$ W5 ]
  95.                             if(!json_cmd.RunCount)* @  B3 p  H( X( U
  96.                                 {
    + b2 r$ y( s; M; m: k$ [7 K& |( X
  97.                                     //printf("no RunCount!\n");+ \0 }! v0 h# ?1 H
  98. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    1 X& E% v2 \/ p
  99.                                 }. ]& R" i. F# c* Y3 A" ~5 k
  100.                             else
    / j8 w  ^3 \, [" ~5 H7 j
  101.                                 {4 w; {! k- J! V6 h8 t+ h$ s
  102.                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);
    ; s+ O7 j1 s# j* m. v# q4 M
  103.                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;+ d. c- T9 ]6 @  D/ k. e
  104.                                 }, {0 x. F1 @& _! v* r9 ~
  105.                                 //开始位置
    6 p7 t! y) |& P% v4 g
  106.                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");* O, f& G3 C' a
  107.                             if(!json_cmd.StartPosition)
    7 X! _( f, j* y& _
  108.                                 {
    1 u- Z: l; I" G1 F* x1 P
  109.                                     //printf("no StartPosition!\n");
    0 W0 F, o5 b* N3 W6 N% x2 W
  110. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0" t5 w# j) G6 |' Y$ O9 w
  111.                                 }
    & g, L  m" y# e' f, Z
  112.                             else
    $ j: m' l, w6 e) Q8 F) E4 O  m
  113.                                 {
    ' L" d% O8 l# C
  114.                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);1 u3 t' S. O' ^5 X. \" v: A
  115.                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;- ~$ Z$ ?! L) R7 A
  116.                                 }6 X0 V' a  e/ f9 ^. ], V7 ~" j
  117.                                 //结束位置9 b8 f6 [+ Z# p0 q' N) H4 s% V' k. \
  118.                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");1 I, Z% [0 U! h2 l) H7 n
  119.                             if(!json_cmd.EndPosition)
    ' D/ D- n1 o* ~( H, `
  120.                                 {4 @6 U- f+ K; d1 S$ K# P7 ?5 Q
  121.                                     //printf("no EndPosition!\n");# R5 @* R% x' A0 O$ E
  122. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0" O6 a: e$ Z+ k8 u4 x- R
  123.                                 }
    + t! K' v6 i5 {( @
  124.                             else) W! b1 B# i+ }6 k, Z8 u
  125.                                 {$ e2 g7 [9 E2 i0 A' K4 x0 U, d
  126.                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);
    5 `- n* {( Y( l! r/ l+ s3 N
  127.                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
    % R0 K) g1 }! _; L9 T+ p) X: A
  128.                                 }% M6 C( I1 Q4 }
  129.                                 //目标位置TargetPosition+ D2 {2 J9 d% O7 A$ I' d
  130.                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");# }& S- r1 R6 z& |1 j$ ]
  131.                             if(!json_cmd.TargetPosition)5 W: p  ?$ Q1 b0 p9 ~
  132.                                 {
    8 w& r0 m2 X. c' [# X
  133.                                     //printf("no TargetPosition!\n");6 }* e. T: o: C- d
  134. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    1 n6 p7 Z7 b6 f) O5 l4 X0 |
  135.                                 }
    & v6 H8 ^8 b# c% w
  136.                             else+ n6 E1 j9 u( h+ |
  137.                                 {2 s$ P. O- @$ B  l) s" X; K
  138.                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);
    8 a4 X% R( n) W# n6 P$ o8 T# K
  139.                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
    $ R! T( Y1 @- d2 @$ }; q6 x8 J6 h# C2 U
  140.                                 }( f/ F  z$ M3 ], w# o9 o0 Y5 I- O. P# c
  141.   j  D# ~1 P! h& f
  142.                                 //*工作模式WorkMode;* @9 I; A( k8 b) y; T" T* ?# G
  143.                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");
    ! q! b4 H. q" t: g6 s) p
  144.                                 if(!json_cmd.WorkMode)5 R# X; @) V" X0 M, Z, l
  145.                                 {
    # {9 S: P8 [% {4 n1 i% r
  146.                                     //printf("no WorkMode!\n");
      ^$ I* |4 w+ q2 v
  147. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    : N* `/ g8 x3 F
  148.                                 }
    ) j7 p# p2 T$ f9 G2 R. ]7 _
  149.                             else
    + x% z2 l6 K- Q, s
  150.                                 {$ R$ ^: s" y  v$ U
  151.                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);
    7 m2 v, I6 J) @; U6 g7 l+ F" J1 @
  152.                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);
    : m4 W2 x- f& k5 i- @5 ]/ v( N
  153.                                 }
    . p# |% K3 `1 C/ v' ?. Q
  154.                                 //step
    + \* n# t( I) m6 }+ O2 Q  w
  155.                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");7 }& A3 w; Q) P  k6 n
  156.                                 if(!json_cmd.Step)
    $ `( d) Q$ Q3 Z) H* H1 A
  157.                                 {8 n+ G) z( |' z1 |% k
  158.                                     //printf("no Step!\n");
    / I2 y2 N( F' |; m( t- X! A7 S* B  C
  159. //                                        cmdtype=NOCOMMAND;//如果没有,就直接返回0
    0 ^4 V2 C, a3 y$ e/ w
  160.                                 }
    : q* [, q9 x% n1 i- H- r
  161.                             else
    ) e, W4 p  n( s2 n
  162.                                 {8 g5 v- k4 n* V! ^! X
  163.                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
    * r0 d8 `* ^, s9 R0 D
  164.                                             Cmd_From_Server.Step=json_cmd.Step->valueint;0 o& c! I% a1 X: F3 |$ K" c# |
  165.                                 }
    * m! X2 d# P& b  z' n3 q/ ^* d- |0 ~
  166. 8 E( Q+ z8 D" \: z5 s& G1 N! _
  167. 9 J% f+ [% R) z
  168.                                 cmdtype= COMMAND;
    ) q4 t: W; a* H: w9 k

  169. / _# M) K8 y* V# H
  170.                         }
    - b6 g6 o/ B  \
  171.              }3 F% x! p) A8 Z2 w

  172.   ~8 ]: [# H. Y9 c: \& ?7 e+ g) Z
  173. cJSON_Delete(root);
    " h3 N( _* q: T& A5 B1 r- _' n" |
  174. # U6 v! `& f9 r7 F) ^
  175. return cmdtype;# z/ B. j% W* X5 f; l9 x4 J
  176. }
复制代码

- X- e1 [0 g- B  A3 S$ \+ h. g7 Q' u! {
8 s4 R7 t! W2 W% N7 \: ^. m& R
收藏 评论0 发布时间:2022-1-28 19:01

举报

0个回答

所属标签

相似分享

官网相关资源

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