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/

    原文出处

  • 相关阅读:
    hdu 4520 小Q系列故事——最佳裁判 解题报告
    hdu 4505 小Q系列故事——电梯里的爱情 解题报告
    hdu 4524 郑厂长系列故事——逃离迷宫 解题报告
    JAVA泛类型示例
    Perl多进程处理Web日志
    Perl单线程日志分析工具
    Perl DBI使用实例
    JAVA(时间对比排序程序)
    软件通信之HTTP通信协议
    Android中级之网络数据解析一之Json解析
  • 原文地址:https://www.cnblogs.com/skullboyer/p/8152011.html
Copyright © 2011-2022 走看看