zoukankan      html  css  js  c++  java
  • 【转】cJSON 源码分析

    cJSON源码分析

    • 简介

      由于C语言汇总,没有直接的字典,字符串数组等数据结构,所以要借助结构体定义,处理json。

      JSON是一种轻量级的数据交换格式。JSON采用完全独立与语言的文本格式,易于人阅读和编写。同时也易于机器解析和生成。它是基于JavaScript,Programming Language,Standard ECMA-262 3rd Edition -December 1999的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(如C,C++,C++,JavaScript,Perl,Python等)。这些特性使用JSON成为理想的数据交换语言。

      JSON作用:在数据传输时能够更好地提取出需要的数据,可以用于客户端和服务器端的数据交互。

      JSON建构与两种结构:

      • “名称/值”对的集合。不同的语言中,它被理解为对象(Object),记录(Record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(Key list),或者关联数组(Associative array)。
      • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

      JSON的结构可以理解成无序的、可嵌套的key-value键值对集合,这些key-value键值对是以结构体或数组的形式来组织的。同一级的key-value键值对之间是用以个“,”(逗号)隔开,每个key-value键值对是由一个key后面紧接一个“:”(冒号),冒号后面是这个key对应的value。Key是一个word,由大小写字母、下划线及数字组成,可以由双引号封闭,也可以不加双引号;而value值的取值为:字符串(string),数值(number),true,false,null,对象(object)或者数组(array)。这些结构可以嵌套。

      实质:JSON是一种信息交换格式,而cJSON就是对JSON格式的字符串进行构建和解析的一个C语言函数库。此外,cJSON作为JSON格式的解析库,其主要功能就是构建和解析JSON格式。

      JSON具有的形式如下:

      对象是一个无序的“名称/值”对集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’”对之间使用“,”(逗号)分割。其具体形式如下图:

      数值是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分割。其具体形式如下图:

      值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者数组(array)。这些结构可以嵌套。其具体形式如下:

      字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符馋(character string)。字符串(string)与C或者Java的字符串非常相似。其具体形式如下:

      数值(number)也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。其具体形式如下:

    JSON格式举例如下:

     1  对象: 名称/值的集合
     2     例:{"firstName":"Tom"}
     3     数组: 值的序列
     4         例:[310, null, 0.231, -2.3E+5]
     5     字符串:
     6         例:"cJSON"
     7     数字:
     8         例:500
     9     布尔值:
    10         例:true false
    • cJSON源码分析

      1)cJSON源码下载,网址为: http://sourceforge.net/projects/cjson/

      2)解压后,主要参看的源码文件为cJSON.h和sJSON.c和test.c,其中test.c为测试函数。

      由于cJSON为JSON格式的解析库,故主要功能是构建和解析JSON格式。其中的结构体,函数定义实现等都是围绕这两个函数实现。下面将对其源码进行分析。

      JSON的内存结构不是树,像广义表,可以认为是有层次的双向链表。

      cJSON中的重要接口函数如下:

       1 解析函数
       2 cJSON * cJSON_Parse(const char *value);
       3 打印函数
       4 char * cJSON_Print(cJSON * item);
       5 删除函数
       6 void  cJSON_Delete(cJSON * c);
       7 构造函数
       8 create系列和add系列
       9 解析字符串
      10 char *parse_string(cJSON*item,const char *str)
      11 解析数字
      12 char *parse_number(cJSON *item,const char *num)
      13 解析数组
      14 char *parse_array(cJSON *item,const char *value)
      15 解析对象
      16 char *parse_object(cJSON *item,const char *value)
      17 ......
    • cJSON程序中的细节点如下:

      • 大量宏替换
      • 大量静态函数
      • 错误处理机制
      • 字符串处理时存在utf16转utf9,编码转换
      • 用函数指针封装malloc,free,方便用于处理,比如在申请后初始化,或者释放前进行一些处理等。

      CJSON的节点结构体如下:

       1 // JSON的一个value的结构体
       2 typedef struct cJSON
       3 {
       4     struct cJSON *next,*prev;    // 同一级的元素使用双向列表存储
       5     struct cJSON *child;           // 如果是一个object或array的话,child为第一个儿子的指针
       6 
       7     int type;                            // value的类型
       8 
       9     char *valuestring;             // 如果这个value是字符串类型,则此处为字符串值
      10     int valueint;                      // 如果是数字的话,整数值
      11     double valuedouble;            // 如果是数字的话,读点数值
      12 
      13     char *string;                      // 如果是对象的key-value元素的话,key值
      14 } cJSON;
      15 
      16 // JSON的类型
      17 #define cJSON_False 0
      18 #define cJSON_True 1
      19 #define cJSON_NULL 2
      20 #define cJSON_Number 3
      21 #define cJSON_String 4
      22 #define cJSON_Array 5
      23 #define cJSON_Object 6
      24 
      25 #define cJSON_IsReference 256
      26 #define cJSON_StringIsConst 512

      cJSON中的内存管理使用了HOOK技术,主要是为了方便使用者自己定义内存管理函数,即用户自定义的malloc和free。下面对其内存管理相关程序分析。

       1 // json内存管理
       2 // 为方便用户自由的管理内存,其使用了Hook技术让使用者可以自定义内存管理函数
       3 typedef struct cJSON_Hooks
       4 {
       5   void *(*malloc_fn)(size_t sz);
       6   void (*free_fn)(void *ptr);
       7 } cJSON_Hooks;
       8 
       9 // 对cJSON提供的分配,再分配,释放内存初始化函数
      10 extern void cJSON_InitHooks(cJSON_Hooks* hooks);
      11 
      12 // 默认将分配和释放空间函数指针指向malloc和free
      13 static void *(*cJSON_malloc)(size_t sz) = malloc;
      14 static void (*cJSON_free)(void *ptr) = free;
      15 // 其使用Hook技术来让使用者可以自定义内存管理函数。其中默认系统使用的内存分配和释放函数是malloc
      16 // 和free函数,利用cJSON_InitHooks函数可以替换成用户自定义的malloc和free函数。
      17 void cJSON_InitHooks(cJSON_Hooks* hooks)
      18 {
      19         // 如果未定义,则使用默认的malloc和free函数
      20     if (!hooks) { /* Reset hooks */
      21         cJSON_malloc = malloc;
      22         cJSON_free = free;
      23         return;
      24     }
      25     // 定义了,则使用用户自定义的malloc和free函数
      26     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
      27     cJSON_free   = (hooks->free_fn)?hooks->free_fn:free;
      28 }

      构建JSON格式数据,首先调用CJSON_CreateObject()函数,返回一个类型为cJSON_Object的cJSON的结构体,这其中调用了CJSON_CreateNULL()、CJSON_CreateTrue()、…、创建不同类型数据的CJSON结构其。在构建过程中,调用CJSON_New_Item创建对应节点信息;然后调用cJSON_AddItemToObject()并结合不同的对象类型增加节点名称和子节点。然后在其中调用cJSON_AddItemToArray()函数来添加信息,此函数中判断对象孩子结点是否为NULL,如果是NULL,则直接插入,否则找到最后一个孩子,调用suffix_object()函数添加到双向链表的尾部。具体程序如下。

       1 // 利用宏函数来快速增加cJSON相关节点信息
       2 // 创建一个string值为name的cJSON_Null节点,并添加到object
       3 #define cJSON_AddNullToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateNull())
       4 // 创建一个string值为name的cJSON_True节点,并添加到object
       5 #define cJSON_AddTrueToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
       6 // 创建一个string值为name的cJSON_False节点,并添加到object
       7 #define cJSON_AddFalseToObject(object,name)     cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
       8 // 创建一个string值为name的cJSON_CreateBool节点,并添加到object。b非0为cJSON_True,0为cJSON_False。
       9 #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
      10 // 创建一个string值为name,valuedouble为n,valueint为(int)n的cJSON_Number节点,并添加到object。
      11 #define cJSON_AddNumberToObject(object,name,n)  cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
      12 // 创建一个string值为name,valuestring为s的cJSON_String节点,并添加到object。
      13 #define cJSON_AddStringToObject(object,name,s)  cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
      14 
      15 // 函数解析
      16 // 输入参数无
      17 // 返回值:指向一个cJSON_Object类型节点的指针
      18 // 创建一个cJSON节点,并设置节点类型无cJSON_Object
      19 extern cJSON *cJSON_CreateObject(void);
      20 
      21 cJSON *cJSON_CreateObject(void)
      22 {
      23     // 创建节点
      24     cJSON *item=cJSON_New_Item();
      25     if(item)
      26         item->type=cJSON_Object;
      27     return item;
      28 }
      29 
      30 // 创建value节点
      31 static cJSON *cJSON_New_Item(void)
      32 {
      33     // 分配空间
      34     cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
      35     // 分配成功后,初始化为0
      36     if (node) memset(node,0,sizeof(cJSON));
      37     return node;
      38 }
      39 
      40 // object(cJSON *):被添加节点的节点
      41 // string(char *):要添加节点的名称
      42 // item(cJSON *):要添加节点
      43 // 返回值无
      44 // 函数功能:将item节点的名称设置为string。如果object节点没有子节点,就将item设置为object
      45 // 子节点,否则将item添加到object->child链表的尾部,成为object->child的兄弟节点
      46 extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
      47 
      48 // 将字符串添加进对象
      49 void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)
      50 {
      51     if (!item)
      52      return;
      53     if (item->string)
      54         cJSON_free(item->string);         // 这个儿子之前有key,先清理
      55     item->string=cJSON_strdup(string);    // 设置key值
      56     cJSON_AddItemToArray(object,item);    // 添加儿子
      57 }
      58 
      59 // 将传入的字符串复制一副本并返回新的字符串指针
      60 static char* cJSON_strdup(const char* str)
      61 {
      62       size_t len;
      63       char* copy;
      64 
      65       len = strlen(str) + 1;
      66             // 分配空间
      67       if (!(copy = (char*)cJSON_malloc(len)))
      68                 return 0;
      69             // 执行复制操作
      70       memcpy(copy,str,len);
      71             // 返回复制的副本
      72       return copy;
      73 }
      74 
      75 // 添加节点到object或array中
      76 void cJSON_AddItemToArray(cJSON *array, cJSON *item)
      77 {
      78     cJSON *c=array->child;
      79     if (!item)
      80         return;
      81     if (!c)
      82     {
      83         array->child=item;     // 之前不存在儿子节点,直接添加
      84     }
      85     else
      86     {
      87         while (c && c->next)   // 先找到最后一个儿子
      88             c=c->next;
      89         suffix_object(c,item); // 添加儿子,c是item的兄弟节点
      90     }
      91 }
      92 
      93 // array的处理
      94 static void suffix_object(cJSON *prev,cJSON *item)
      95 {
      96     // 两个兄弟的指针互相指向对方
      97     prev->next=item;
      98     item->prev=prev;
      99 }

      JSON解析数据格式时所调用的函数过程如下:

      首选,调用cJSON_Parse()函数,此函数是一个二次封装函数,其内部为cJSON_ParseWithOpts()函数,该函数用于提取更多的解析选项,如果需要,最后返回解析结束的位置。而在上面的函数中,调用parse_value()函数进行解析,而该函数首先创建cJSON_NewItem()创建节点,用于存放解析的JSON结构数据,然后根据不同的选项,调用解析函数,其为parse_string(),parse_number(),parse_array(),parse_objec()等。其程序解析如下:

        1 // cJSON解析的二次封装函数
        2 cJSON *cJSON_Parse(const char *value)
        3 {
        4     return cJSON_ParseWithOpts(value,0,0);
        5 }   
        6 
        7 // 解析对象,创建一个新的根并初始化,返回一个cJSON类型
        8 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
        9 {
       10     const char *end=0;
       11     cJSON *c=cJSON_New_Item();
       12     ep=0;
       13     if (!c)
       14         return 0;       /* memory fail */
       15 
       16     end=parse_value(c,skip(value));
       17     if (!end)
       18     {
       19         cJSON_Delete(c);
       20         return 0;
       21     }   /* parse failure. ep is set. */
       22 
       23     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
       24     if (require_null_terminated)
       25     {
       26         end=skip(end);
       27         if (*end)
       28         {
       29             cJSON_Delete(c);
       30             ep=end;
       31             return 0;
       32         }
       33     }
       34     if (return_parse_end)
       35         *return_parse_end=end;
       36     return c;
       37 }
       38 
       39 // 解析器核心函数
       40 static const char *parse_value(cJSON *item,const char *value)
       41 {
       42     if (!value)
       43         return 0;   /* Fail on null. */
       44     if (!strncmp(value,"null",4))
       45     {
       46         item->type=cJSON_NULL;
       47         return value+4;
       48     }
       49     if (!strncmp(value,"false",5))
       50     {
       51         item->type=cJSON_False;
       52         return value+5;
       53     }
       54     if (!strncmp(value,"true",4))
       55     {
       56         item->type=cJSON_True;
       57         item->valueint=1;
       58         return value+4;
       59     }
       60     if (*value=='"')
       61     {
       62         return parse_string(item,value);
       63     }
       64     if (*value=='-' || (*value>='0' && *value<='9'))
       65     {
       66         return parse_number(item,value);
       67     }
       68     if (*value=='[')
       69     {
       70         return parse_array(item,value);
       71     }
       72     if (*value=='{')
       73     {
       74         return parse_object(item,value);
       75     }
       76 
       77     ep=value;
       78     return 0;   /* failure. */
       79 }
       80 
       81 static const char *parse_string(cJSON *item,const char *str)
       82 {
       83     const char *ptr=str+1;
       84     char *ptr2;
       85     char *out;
       86     int len=0;
       87     unsigned uc,uc2;
       88     if (*str!='"')    // 不是字符串情况
       89     {
       90         ep=str;
       91         return 0;
       92     }   /* not a string! */
       93 
       94     while (*ptr!='"' && *ptr && ++len)
       95         if (*ptr++ == '\')
       96             ptr++;   // 跳出前面的引用
       97 
       98     out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
       99     if (!out)
      100         return 0;
      101 
      102     ptr=str+1;
      103     ptr2=out;
      104     while (*ptr!='"' && *ptr)
      105     {
      106         if (*ptr!='\')
      107             *ptr2++=*ptr++;
      108         else
      109         {
      110             ptr++;
      111             switch (*ptr)
      112             {
      113                 case 'b': *ptr2++=''; break;
      114                 case 'f': *ptr2++='f'; break;
      115                 case 'n': *ptr2++='
      '; break;
      116                 case 'r': *ptr2++='
      '; break;
      117                 case 't': *ptr2++='	'; break;
      118                 case 'u':    /* transcode utf16 to utf8. */
      119                     uc=parse_hex4(ptr+1);
      120                         ptr+=4; /* get the unicode char. */
      121 
      122                     if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
      123                         break;  /* check for invalid.   */
      124 
      125                     if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.   */
      126                     {
      127                         if (ptr[1]!='\' || ptr[2]!='u')
      128                             break;  /* missing second-half of surrogate.    */
      129                         uc2=parse_hex4(ptr+3);ptr+=6;
      130                         if (uc2<0xDC00 || uc2>0xDFFF)
      131                             break;  /* invalid second-half of surrogate.    */
      132                         uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
      133                     }
      134 
      135                     len=4;
      136                     if (uc<0x80)
      137                         len=1;
      138                     else if (uc<0x800)
      139                         len=2;
      140                     else if (uc<0x10000)
      141                         len=3;
      142                     ptr2+=len;
      143 
      144                     switch (len)
      145                     {
      146                         case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
      147                         case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
      148                         case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
      149                         case 1: *--ptr2 =(uc | firstByteMark[len]);
      150                     }
      151                     ptr2+=len;
      152                     break;
      153                 default:  *ptr2++=*ptr; break;
      154             }
      155             ptr++;
      156         }
      157     }
      158     *ptr2=0;
      159     if (*ptr=='"') ptr++;
      160     item->valuestring=out;
      161     item->type=cJSON_String;
      162     return ptr;
      163 }
      164 
      165 // 跳过这些空格
      166 static const char *skip(const char *in)
      167 {
      168     while (in && *in && (unsigned char)*in<=32)
      169         in++;
      170     return in;
      171 }
      172 
      173 // parse_number函数功能:解析数字,对输入的文本生成一个数字,并填充结果项,传入参数有两
      174 // 个,这里先只关注num,返回值是一个字符串
      175 static const char *parse_number(cJSON *item,const char *num)
      176 {
      177     double n=0,sign=1,scale=0;
      178     int subscale=0,signsubscale=1;
      179 
      180     if (*num=='-') sign=-1,num++;      // 判断数字是否是有符号数字
      181     if (*num=='0') num++;                  // 判断数字是否为0
      182     if (*num>='1' && *num<='9')
      183         do                               // 转换数字
      184             n=(n*10.0)+(*num++ -'0');
      185         while (*num>='0' && *num<='9');
      186     if (*num=='.' && num[1]>='0' && num[1]<='9') // 对小数点后边的部分进行处理,scale记录小数点后边的位数
      187     {
      188         num++;
      189         do
      190             n=(n*10.0)+(*num++ -'0'),scale--;       // scale为小数点后的位数
      191         while (*num>='0' && *num<='9');
      192     }
      193     if (*num=='e' || *num=='E')        // 是否为指数,科学计数法
      194     {
      195         num++;
      196         if (*num=='+')                 // 判断指数后边幂的正负号
      197             num++;
      198         else if (*num=='-')
      199             signsubscale=-1,num++;
      200         while (*num>='0' && *num<='9') // 处理指数后边10的幂
      201             subscale=(subscale*10)+(*num++ - '0');
      202     }
      203     // 将字符串转换为相应的数值
      204     n=sign*n*pow(10.0,(scale+subscale*signsubscale));   /* number = +/- number.fraction * 10^+/- exponent */
      205 
      206     item->valuedouble=n;             // 将算出来的值存入缓存
      207     item->valueint=(int)n;           // 将算出来的值存入缓存
      208     item->type=cJSON_Number;         // 目标类型为数字
      209     return num;
      210 }
      211 
      212 // 从输入文本中构建array
      213 static const char *parse_array(cJSON *item,const char *value)
      214 {
      215     cJSON *child;
      216     if (*value!='[')    {ep=value;return 0;}    /* not an array! */
      217 
      218     item->type=cJSON_Array;
      219     value=skip(value+1);
      220     if (*value==']') return value+1;    /* empty array. */
      221 
      222     item->child=child=cJSON_New_Item();
      223     if (!item->child) return 0;      /* memory fail */
      224     value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
      225     if (!value) return 0;
      226 
      227     while (*value==',')
      228     {
      229         cJSON *new_item;
      230         if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
      231         child->next=new_item;new_item->prev=child;child=new_item;
      232         value=skip(parse_value(child,skip(value+1)));
      233         if (!value) return 0;   /* memory fail */
      234     }
      235 
      236     if (*value==']') return value+1;    /* end of array */
      237     ep=value;return 0;  /* malformed. */
      238 }
      239 
      240 // 从输入文本中构建object
      241 static const char *parse_object(cJSON *item,const char *value)
      242 {
      243     cJSON *child;
      244     if (*value!='{')    {ep=value;return 0;}    /* not an object! */
      245 
      246     item->type=cJSON_Object;
      247     value=skip(value+1);
      248     if (*value=='}') return value+1;    /* empty array. */
      249 
      250     item->child=child=cJSON_New_Item();
      251     if (!item->child) return 0;
      252     value=skip(parse_string(child,skip(value)));
      253     if (!value) return 0;
      254     child->string=child->valuestring;child->valuestring=0;
      255     if (*value!=':') {ep=value;return 0;}   /* fail! */
      256     value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
      257     if (!value) return 0;
      258 
      259     while (*value==',')
      260     {
      261         cJSON *new_item;
      262         if (!(new_item=cJSON_New_Item()))   return 0; /* memory fail */
      263         child->next=new_item;new_item->prev=child;child=new_item;
      264         value=skip(parse_string(child,skip(value+1)));
      265         if (!value) return 0;
      266         child->string=child->valuestring;child->valuestring=0;
      267         if (*value!=':') {ep=value;return 0;}   /* fail! */
      268         value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
      269         if (!value) return 0;
      270     }
      271 
      272     if (*value=='}') return value+1;    /* end of array */
      273     ep=value;return 0;  /* malformed. */
      274 }
      275 
      276 // 将十六进制的字符串转换为数字表示!
      277 static unsigned parse_hex4(const char *str)
      278 {
      279     unsigned h=0;
      280     if (*str>='0' && *str<='9')
      281         h+=(*str)-'0';
      282     else if (*str>='A' && *str<='F')
      283         h+=10+(*str)-'A';
      284     else if (*str>='a' && *str<='f')
      285         h+=10+(*str)-'a';
      286     else
      287         return 0;
      288     h=h<<4;str++;
      289     if (*str>='0' && *str<='9')
      290         h+=(*str)-'0';
      291     else if (*str>='A' && *str<='F')
      292         h+=10+(*str)-'A';
      293     else if (*str>='a' && *str<='f')
      294         h+=10+(*str)-'a';
      295     else
      296         return 0;
      297     h=h<<4;str++;
      298     if (*str>='0' && *str<='9')
      299         h+=(*str)-'0';
      300     else if (*str>='A' && *str<='F')
      301         h+=10+(*str)-'A';
      302     else if (*str>='a' && *str<='f')
      303         h+=10+(*str)-'a';
      304     else
      305         return 0;
      306     h=h<<4;str++;
      307     if (*str>='0' && *str<='9')
      308         h+=(*str)-'0';
      309     else if (*str>='A' && *str<='F')
      310         h+=10+(*str)-'A';
      311     else if (*str>='a' && *str<='f')
      312         h+=10+(*str)-'a';
      313     else
      314         return 0;
      315     return h;
      316 }
      317 
      318 打印JSON信息
      319 
      320 // 打印值到文本
      321 static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
      322 {
      323     char *out=0;
      324     if (!item) return 0;
      325     if (p)
      326     {
      327         switch ((item->type)&255)
      328         {
      329             case cJSON_NULL:    {out=ensure(p,5);   if (out) strcpy(out,"null");    break;}
      330             case cJSON_False:   {out=ensure(p,6);   if (out) strcpy(out,"false");   break;}
      331             case cJSON_True:    {out=ensure(p,5);   if (out) strcpy(out,"true");    break;}
      332             case cJSON_Number:  out=print_number(item,p);break;
      333             case cJSON_String:  out=print_string(item,p);break;
      334             case cJSON_Array:   out=print_array(item,depth,fmt,p);break;
      335             case cJSON_Object:  out=print_object(item,depth,fmt,p);break;
      336         }
      337     }
      338     else
      339     {
      340         switch ((item->type)&255)
      341         {
      342             case cJSON_NULL:    out=cJSON_strdup("null");   break;
      343             case cJSON_False:   out=cJSON_strdup("false");break;
      344             case cJSON_True:    out=cJSON_strdup("true"); break;
      345             case cJSON_Number:  out=print_number(item,0);break;
      346             case cJSON_String:  out=print_string(item,0);break;
      347             case cJSON_Array:   out=print_array(item,depth,fmt,0);break;
      348             case cJSON_Object:  out=print_object(item,depth,fmt,0);break;
      349         }
      350     }
      351     return out;
      352 }
      353 
      354 // 打印array到文本
      355 static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
      356 {
      357     char **entries;
      358     char *out=0,*ptr,*ret;int len=5;
      359     cJSON *child=item->child;
      360     int numentries=0,i=0,fail=0;
      361     size_t tmplen=0;
      362 
      363     /* How many entries in the array? */
      364     while (child) numentries++,child=child->next;
      365     /* Explicitly handle numentries==0 */
      366     if (!numentries)
      367     {
      368         if (p)  out=ensure(p,3);
      369         else    out=(char*)cJSON_malloc(3);
      370         if (out) strcpy(out,"[]");
      371         return out;
      372     }
      373 
      374     if (p)
      375     {
      376         /* Compose the output array. */
      377         i=p->offset;
      378         ptr=ensure(p,1);if (!ptr) return 0; *ptr='[';   p->offset++;
      379         child=item->child;
      380         while (child && !fail)
      381         {
      382             print_value(child,depth+1,fmt,p);
      383             p->offset=update(p);
      384             if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
      385             child=child->next;
      386         }
      387         ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
      388         out=(p->buffer)+i;
      389     }
      390     else
      391     {
      392         /* Allocate an array to hold the values for each */
      393         entries=(char**)cJSON_malloc(numentries*sizeof(char*));
      394         if (!entries) return 0;
      395         memset(entries,0,numentries*sizeof(char*));
      396         /* Retrieve all the results: */
      397         child=item->child;
      398         while (child && !fail)
      399         {
      400             ret=print_value(child,depth+1,fmt,0);
      401             entries[i++]=ret;
      402             if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
      403             child=child->next;
      404         }
      405 
      406         /* If we didn't fail, try to malloc the output string */
      407         if (!fail)  out=(char*)cJSON_malloc(len);
      408         /* If that fails, we fail. */
      409         if (!out) fail=1;
      410 
      411         /* Handle failure. */
      412         if (fail)
      413         {
      414             for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
      415             cJSON_free(entries);
      416             return 0;
      417         }
      418 
      419         /* Compose the output array. */
      420         *out='[';
      421         ptr=out+1;*ptr=0;
      422         for (i=0;i<numentries;i++)
      423         {
      424             tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
      425             if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
      426             cJSON_free(entries[i]);
      427         }
      428         cJSON_free(entries);
      429         *ptr++=']';*ptr++=0;
      430     }
      431     return out;
      432 }
      433 
      434 // 打印object到文本中
      435 static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
      436 {
      437     char **entries=0,**names=0;
      438     char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
      439     cJSON *child=item->child;
      440     int numentries=0,fail=0;
      441     size_t tmplen=0;
      442     /* Count the number of entries. */
      443     while (child) numentries++,child=child->next;
      444     /* Explicitly handle empty object case */
      445     if (!numentries)
      446     {
      447         if (p) out=ensure(p,fmt?depth+4:3);
      448         else    out=(char*)cJSON_malloc(fmt?depth+4:3);
      449         if (!out)   return 0;
      450         ptr=out;*ptr++='{';
      451         if (fmt) {*ptr++='
      ';for (i=0;i<depth-1;i++) *ptr++='	';}
      452         *ptr++='}';*ptr++=0;
      453         return out;
      454     }
      455     if (p)
      456     {
      457         /* Compose the output: */
      458         i=p->offset;
      459         len=fmt?2:1;    ptr=ensure(p,len+1);    if (!ptr) return 0;
      460         *ptr++='{'; if (fmt) *ptr++='
      ';   *ptr=0; p->offset+=len;
      461         child=item->child;depth++;
      462         while (child)
      463         {
      464             if (fmt)
      465             {
      466                 ptr=ensure(p,depth);    if (!ptr) return 0;
      467                 for (j=0;j<depth;j++) *ptr++='	';
      468                 p->offset+=depth;
      469             }
      470             print_string_ptr(child->string,p);
      471             p->offset=update(p);
      472 
      473             len=fmt?2:1;
      474             ptr=ensure(p,len);  if (!ptr) return 0;
      475             *ptr++=':';if (fmt) *ptr++='	';
      476             p->offset+=len;
      477 
      478             print_value(child,depth,fmt,p);
      479             p->offset=update(p);
      480 
      481             len=(fmt?1:0)+(child->next?1:0);
      482             ptr=ensure(p,len+1); if (!ptr) return 0;
      483             if (child->next) *ptr++=',';
      484             if (fmt) *ptr++='
      ';*ptr=0;
      485             p->offset+=len;
      486             child=child->next;
      487         }
      488         ptr=ensure(p,fmt?(depth+1):2);   if (!ptr) return 0;
      489         if (fmt)    for (i=0;i<depth-1;i++) *ptr++='	';
      490         *ptr++='}';*ptr=0;
      491         out=(p->buffer)+i;
      492     }
      493     else
      494     {
      495         /* Allocate space for the names and the objects */
      496         entries=(char**)cJSON_malloc(numentries*sizeof(char*));
      497         if (!entries) return 0;
      498         names=(char**)cJSON_malloc(numentries*sizeof(char*));
      499         if (!names) {cJSON_free(entries);return 0;}
      500         memset(entries,0,sizeof(char*)*numentries);
      501         memset(names,0,sizeof(char*)*numentries);
      502 
      503         /* Collect all the results into our arrays: */
      504         child=item->child;depth++;if (fmt) len+=depth;
      505         while (child)
      506         {
      507             names[i]=str=print_string_ptr(child->string,0);
      508             entries[i++]=ret=print_value(child,depth,fmt,0);
      509             if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
      510             child=child->next;
      511         }
      512 
      513         /* Try to allocate the output string */
      514         if (!fail)  out=(char*)cJSON_malloc(len);
      515         if (!out) fail=1;
      516 
      517         /* Handle failure */
      518         if (fail)
      519         {
      520             for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
      521             cJSON_free(names);cJSON_free(entries);
      522             return 0;
      523         }
      524 
      525         /* Compose the output: */
      526         *out='{';ptr=out+1;if (fmt)*ptr++='
      ';*ptr=0;
      527         for (i=0;i<numentries;i++)
      528         {
      529             if (fmt) for (j=0;j<depth;j++) *ptr++='	';
      530             tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
      531             *ptr++=':';if (fmt) *ptr++='	';
      532             strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
      533             if (i!=numentries-1) *ptr++=',';
      534             if (fmt) *ptr++='
      ';*ptr=0;
      535             cJSON_free(names[i]);cJSON_free(entries[i]);
      536         }
      537 
      538         cJSON_free(names);cJSON_free(entries);
      539         if (fmt) for (i=0;i<depth-1;i++) *ptr++='	';
      540         *ptr++='}';*ptr++=0;
      541     }
      542     return out;
      543 }

      其余函数信息如下:

        1 // 返回节点的个数
        2 int cJSON_GetArraySize(cJSON *array)
        3 {
        4     cJSON *c=array->child;
        5     int i=0;
        6     while(c)
        7         i++,c=c->next;
        8     return i;
        9 }
       10 // 返回array中第item个节点的地址
       11 cJSON *cJSON_GetArrayItem(cJSON *array,int item)
       12 {
       13     cJSON *c=array->child;
       14     while (c && item>0)
       15         item--,c=c->next;
       16     return c;
       17 }
       18 // 返回Object中第item个节点的地址
       19 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)
       20 {
       21     cJSON *c=object->child;
       22     while (c && cJSON_strcasecmp(c->string,string))
       23         c=c->next;
       24     return c;
       25 }
       26 
       27 // 在链表中插入一个新的节点
       28 void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem)
       29 {
       30     cJSON *c=array->child;
       31     // 找到which位置
       32     while (c && which>0)
       33      c=c->next,which--;
       34     // 添加新的节点到array中
       35     if (!c)
       36     {
       37         cJSON_AddItemToArray(array,newitem);
       38         return;
       39     }
       40     // 将链表节点进行挂接
       41     newitem->next=c;
       42     newitem->prev=c->prev;
       43     c->prev=newitem;
       44     // 处理arrya的孩子节点
       45     if (c==array->child)
       46         array->child=newitem;
       47     else
       48         newitem->prev->next=newitem;
       49 }
       50 // 替换节点操作,用新的节点替换原有的某一个节点
       51 void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)
       52 {
       53     cJSON *c=array->child;
       54     // 找到which位置
       55     while (c && which>0)
       56         c=c->next,which--;
       57     if (!c)
       58         return;
       59     // 进行挂接
       60     newitem->next=c->next;
       61     newitem->prev=c->prev;
       62     // 处理NULL情况
       63     if (newitem->next)
       64         newitem->next->prev=newitem;
       65     // 处理孩子节点
       66     if (c==array->child)
       67         array->child=newitem;
       68     else
       69         newitem->prev->next=newitem;
       70     c->next=c->prev=0;
       71     // 删除替换的节点
       72     cJSON_Delete(c);
       73 }
       74 // 替换节点操作
       75 // 用原有节点替换现有节点
       76 void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem)
       77 {
       78     int i=0;
       79     cJSON *c=object->child;
       80     while(c && cJSON_strcasecmp(c->string,string))
       81         i++,c=c->next;
       82     if(c)
       83     {
       84         newitem->string=cJSON_strdup(string);
       85         cJSON_ReplaceItemInArray(object,i,newitem);
       86     }
       87 }
       88 
       89 /* Create basic types: */
       90 // 创建基本类型函数
       91 cJSON *cJSON_CreateNull(void)
       92 {
       93     cJSON *item=cJSON_New_Item();
       94     if(item)
       95         item->type=cJSON_NULL;
       96     return item;
       97 }
       98 cJSON *cJSON_CreateTrue(void)
       99 {
      100     cJSON *item=cJSON_New_Item();
      101     if(item)
      102         item->type=cJSON_True;
      103     return item;
      104 }
      105 cJSON *cJSON_CreateFalse(void)
      106 {
      107     cJSON *item=cJSON_New_Item();
      108     if(item)
      109         item->type=cJSON_False;
      110     return item;
      111 }
      112 cJSON *cJSON_CreateBool(int b)
      113 {
      114     cJSON *item=cJSON_New_Item();
      115     if(item)
      116         item->type=b?cJSON_True:cJSON_False;
      117     return item;
      118 }
      119 cJSON *cJSON_CreateNumber(double num)
      120 {
      121     cJSON *item=cJSON_New_Item();
      122     if(item)
      123     {
      124         item->type=cJSON_Number;
      125         item->valuedouble=num;
      126         item->valueint=(int)num;
      127     }
      128     return item;
      129 }
      130 cJSON *cJSON_CreateString(const char *string)
      131 {
      132     cJSON *item=cJSON_New_Item();
      133     if(item)
      134     {
      135         item->type=cJSON_String;
      136         item->valuestring=cJSON_strdup(string);
      137     }
      138     return item;
      139 }
      140 cJSON *cJSON_CreateArray(void)
      141 {
      142     cJSON *item=cJSON_New_Item();
      143     if(item)
      144         item->type=cJSON_Array;
      145     return item;
      146 }
      147 cJSON *cJSON_CreateObject(void)
      148 {
      149     cJSON *item=cJSON_New_Item();
      150     if(item)
      151         item->type=cJSON_Object;
      152     return item;
      153 }
      154 
      155 /* Create Arrays: */
      156 // 创建array
      157 cJSON *cJSON_CreateIntArray(const int *numbers,int count)
      158 {
      159     int i;
      160     cJSON *n=0,*p=0,*a=cJSON_CreateArray();
      161     for(i=0;a && i<count;i++)
      162     {
      163         n=cJSON_CreateNumber(numbers[i]);
      164         if(!i)
      165             a->child=n;
      166         else
      167             suffix_object(p,n);
      168         p=n;
      169     }
      170     return a;
      171 }
      172 cJSON *cJSON_CreateFloatArray(const float *numbers,int count)
      173 {
      174     int i;
      175     cJSON *n=0,*p=0,*a=cJSON_CreateArray();
      176     for(i=0;a && i<count;i++)
      177     {
      178         n=cJSON_CreateNumber(numbers[i]);
      179         if(!i)
      180             a->child=n;
      181         else
      182             suffix_object(p,n);
      183         p=n;
      184     }
      185     return a;
      186 }
      187 cJSON *cJSON_CreateDoubleArray(const double *numbers,int count)
      188 {
      189     int i;
      190     cJSON *n=0,*p=0,*a=cJSON_CreateArray();
      191     for(i=0;a && i<count;i++)
      192     {
      193         n=cJSON_CreateNumber(numbers[i]);
      194         if(!i)
      195             a->child=n;
      196         else
      197             suffix_object(p,n);
      198         p=n;
      199     }
      200     return a;
      201 }
      202 cJSON *cJSON_CreateStringArray(const char **strings,int count)
      203 {
      204     int i;
      205     cJSON *n=0,*p=0,*a=cJSON_CreateArray();
      206     for(i=0;a && i<count;i++)
      207     {
      208         n=cJSON_CreateString(strings[i]);
      209         if(!i)
      210             a->child=n;
      211         else
      212             suffix_object(p,n);
      213         p=n;
      214     }
      215     return a;
      216 }
      217 
      218 /* Duplication */
      219 // 拷贝副本操作
      220 cJSON *cJSON_Duplicate(cJSON *item,int recurse)
      221 {
      222     cJSON *newitem,*cptr,*nptr=0,*newchild;
      223     /* Bail on bad ptr */
      224     if (!item)
      225         return 0;
      226     /* Create new item */
      227     newitem=cJSON_New_Item();
      228     if (!newitem)
      229         return 0;
      230     /* Copy over all vars */
      231     newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
      232     if (item->valuestring)
      233     {
      234         newitem->valuestring=cJSON_strdup(item->valuestring);
      235         if (!newitem->valuestring)
      236         {
      237             cJSON_Delete(newitem);
      238             return 0;
      239         }
      240     }
      241     if (item->string)
      242     {
      243         newitem->string=cJSON_strdup(item->string);
      244         if (!newitem->string)
      245         {
      246             cJSON_Delete(newitem);
      247             return 0;
      248         }
      249     }
      250     /* If non-recursive, then we're done! */
      251     if (!recurse)
      252         return newitem;
      253     /* Walk the ->next chain for the child. */
      254     cptr=item->child;
      255     while (cptr)
      256     {
      257         newchild=cJSON_Duplicate(cptr,1);       /* Duplicate (with recurse) each item in the ->next chain */
      258         if (!newchild)
      259         {
      260             cJSON_Delete(newitem);
      261             return 0;
      262         }
      263         if (nptr)
      264         {
      265             nptr->next=newchild,newchild->prev=nptr;
      266             nptr=newchild;
      267         }   /* If newitem->child already set, then crosswire ->prev and ->next and move on */
      268         else
      269         {
      270             newitem->child=newchild;
      271             nptr=newchild;
      272         }                   /* Set newitem->child and move to it */
      273         cptr=cptr->next;
      274     }
      275     return newitem;
      276 }
      277 
      278 void cJSON_Minify(char *json)
      279 {
      280     char *into=json;
      281     while (*json)
      282     {
      283         if (*json==' ') json++;
      284         else if (*json=='	') json++;   /* Whitespace characters. */
      285         else if (*json=='
      ') json++;
      286         else if (*json=='
      ') json++;
      287         else if (*json=='/' && json[1]=='/')  while (*json && *json!='
      ') json++;  /* double-slash comments, to end of line. */
      288         else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   /* multiline comments. */
      289         else if (*json=='"'){*into++=*json++;while (*json && *json!='"'){if (*json=='\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are " sensitive. */
      290         else *into++=*json++;           /* All other characters. */
      291     }
      292     *into=0;    /* and null-terminate. */
      293 }
    • 参考文献

      http://www.0xffffff.org/2014/02/10/29-cjson-analyse/

      http://github.tiankonguse.com/blog/2014/12/18/cjson-source.html

      http://www.codexiu.cn/javascript/blog/21402/

      http://www.json.org/

    原文出处

  • 相关阅读:
    2.Android之按钮Button和编辑框EditText学习
    《DSP using MATLAB》Problem 3.8
    《DSP using MATLAB》Problem 3.7
    《DSP using MATLAB》Problem 3.6
    《DSP using MATLAB》Problem 3.5
    《DSP using MATLAB》Problem 3.4
    《DSP using MATLAB》Problem 3.3
    《DSP using MATLAB》Problem 3.2
    《DSP using MATLAB》Problem 3.1
    《DSP using MATLAB》Problem 2.20
  • 原文地址:https://www.cnblogs.com/skullboyer/p/8152011.html
Copyright © 2011-2022 走看看