zoukankan      html  css  js  c++  java
  • cJSON_hacking

       1 /******************************************************************************
       2  *                              cJSON_hacking
       3  * 
       4  * 1.这是cJSON中cJSON.c(主程序)的源码,源码不到1000行(除注释).
       5  * 2.本文仅仅注释了源码中JSON解析部分,对链表的操作没有进行任何注释,通过
       6  *   分析阅读该源码,可以一窥双向链表,字符串处理,里面几个地方使用到了递归,
       7  *   而且用得很精妙,但在理解上可能会有点困难.
       8  * 3.源码作者在解析JSON时参考了: http://www.json.org/fatfree.html
       9  *   如果您要阅读本程序,请先阅读该网页内容,因为源码中几个重要的函数的处理
      10  *   都参照了该网页上的处理算法.
      11  * 4.知识量:
      12  *     1.C语言;
      13  *     2.2.Unix或类Unix系统编程;
      14  *     3.对双向链表的数据结构清晰;
      15  * 5.如何阅读该源码:
      16  *     1.linux下使用vi/vim配和ctags,windows下使用Source Insight,当然你也
      17  *          可以用其他文本编辑器看.
      18  *     2.该源码无主函数,本人自己是从第一个函数开始阅读,然后慢慢的看懂,
      19  *          并了解了整个源码的大局,但本人强烈建议您从该函数开始阅读:
      20  *          cJSON *cJSON_Parse( const char *value ).
      21  *          主要是因为这是默认的解析函数.
      22  *     3.对于有些函数,本人没有添加注释,或者说本人觉得没必要.
      23  *     4.祝您好运.  :)
      24  *
      25  * 
      26  * 6.cJSON下载url: http://sourceforge.net/projects/cjson/
      27  * 
      28  * 如果您对本文有任何意见、提议,可以发邮件至zengjf42@163.com,会尽快回复.
      29  * 本文的最终解释权归本人(曾剑锋)所有,仅供学习、讨论.
      30  *
      31  *                                          2015-3-3 阴 深圳 尚观 Var
      32  *
      33  ******************************************************************************/
      34 
      35 
      36 /*
      37  * Copyright (c) 2009 Dave Gamble
      38  *
      39  * Permission is hereby granted, free of charge, to any person obtaining a copy
      40  * of this software and associated documentation files (the "Software"), to deal
      41  * in the Software without restriction, including without limitation the rights
      42  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      43  * copies of the Software, and to permit persons to whom the Software is
      44  * furnished to do so, subject to the following conditions:
      45  *
      46  * The above copyright notice and this permission notice shall be included in
      47  * all copies or substantial portions of the Software.
      48  *
      49  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      50  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      51  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      52  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      53  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      54  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      55  * THE SOFTWARE.
      56  */
      57 
      58 /* cJSON */
      59 /* JSON parser in C. */
      60 
      61 #include <string.h>
      62 #include <stdio.h>
      63 #include <math.h>
      64 #include <stdlib.h>
      65 #include <float.h>
      66 #include <limits.h>
      67 #include <ctype.h>
      68 #include "cJSON.h"
      69 
      70 /**
      71  * 返回解析出错时对应的字符地址.
      72  */
      73 static const char *ep; /* error pointer */
      74 const char *cJSON_GetErrorPtr( void )
      75 {
      76     return(ep);
      77 }
      78 
      79 
      80 /**
      81  * 不分大小写字符串比较,感觉和原生的strcasecmp没什么区别.
      82  */
      83 static int cJSON_strcasecmp( const char *s1, const char *s2 )
      84 {
      85     if ( !s1 )
      86         return( (s1 == s2) ? 0 : 1);
      87     if ( !s2 )
      88         return(1);
      89     for (; tolower( *s1 ) == tolower( *s2 ); ++s1, ++s2 )
      90         if ( *s1 == 0 )
      91             return(0);
      92     return(tolower( *(const unsigned char *) s1 ) - tolower( *(const unsigned char *) s2 ));
      93 }
      94 
      95 
      96 /**
      97  * 定义cJSON中内存分配采用的方式,这里直接使用原生的malloc,free函数.
      98  */
      99 static void    *(*cJSON_malloc)(size_t sz)    = malloc;
     100 static void    (*cJSON_free)( void *ptr )    = free;
     101 
     102 
     103 /**
     104  * 定义cJSON中的字符串拷贝函数.
     105  */
     106 static char* cJSON_strdup( const char* str )
     107 {
     108     size_t    len;
     109     char    * copy;
     110 
     111     len = strlen( str ) + 1;
     112     if ( !(copy = (char *) cJSON_malloc( len )))
     113         return(0);
     114     memcpy( copy, str, len );
     115     return(copy);
     116 }
     117 
     118 
     119 /**
     120  * 选择系统使用那种内存分配方式,这里使用原生的malloc、free函数.
     121  */
     122 void cJSON_InitHooks( cJSON_Hooks* hooks )
     123 {
     124     if ( !hooks ) /* Reset hooks */
     125     {
     126         cJSON_malloc    = malloc;
     127         cJSON_free    = free;
     128         return;
     129     }
     130 
     131     cJSON_malloc    = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
     132     cJSON_free    = (hooks->free_fn) ? hooks->free_fn : free;
     133 }
     134 
     135 
     136 /**
     137  * 构造一个item,同时给item赋初始值为全0,item可以理解为一个节点.
     138  */
     139 static cJSON *cJSON_New_Item( void )
     140 {
     141     cJSON* node = (cJSON *) cJSON_malloc( sizeof(cJSON));
     142     if ( node )
     143         memset( node, 0, sizeof(cJSON));
     144     return(node);
     145 }
     146 
     147 
     148 /**
     149  * 释放链表,对于有子链表的链表,采用递归的方式进行内存释放.
     150  * 目前还没找到为什么需要 c->type & cJSON_IsReference 判断.
     151  */
     152 void cJSON_Delete( cJSON *c )
     153 {
     154     cJSON *next;
     155     while ( c )
     156     {
     157         next = c->next;
     158         if ( !(c->type & cJSON_IsReference) && c->child )
     159             cJSON_Delete( c->child );    /* 递归释放内存 */
     160         if ( !(c->type & cJSON_IsReference) && c->valuestring )
     161             cJSON_free( c->valuestring );
     162         if ( c->string )
     163             cJSON_free( c->string );
     164         cJSON_free( c );
     165         c = next;
     166     }
     167 }
     168 
     169 
     170 /* Parse the input text to generate a number, and populate the result into item. */
     171 /**
     172  * 解析数字,并把数据保存在item中对应的的地方.
     173  */
     174 static const char *parse_number( cJSON *item, const char *num )
     175 {
     176     /**
     177      * 局部变量说明:
     178      *     1.n            : 用于保存数字;
     179      *     2.sign         : 数字部分的符号标志,如果是负数,就等于-1,如果是正数,就是1;
     180      *     3.scale        : 保存小数点后面有多少个数字的相反数;
     181      *     4.subscale     : 保存指数后面的数字;
     182      *     5.signsubscale : 指数部分的符号标志,如果是负数,就等于-1,如果是正数,就是1.
     183      *
     184      *  如:
     185      *       num字符串: -1234.1234e4
     186      *          1.n            = 12341234;
     187      *          2.sign         = -1;
     188      *          3.scale        = -4;
     189      *          4.subscale     = 4;
     190      *          5.signsubscale = 1;
     191      *
     192      *          结果公式 = sign * n * pow( 10.0, (scale + subscale * signsubscale))
     193      *        n = -1 * 12341234 * pow( 10.0, (-4 + 4 * 1))
     194      *        n = -12341234 * pow( 10.0, 0 )
     195      *        n = -12341234
     196      */
     197     double n = 0, sign = 1, scale = 0; int subscale = 0, signsubscale = 1;
     198 
     199     if ( *num == '-' )
     200         sign = -1, num++;         /* Has sign? */
     201     if ( *num == '0' )
     202         num++;                    /* is zero */
     203     if ( *num >= '1' && *num <= '9' )
     204         do
     205             n = (n * 10.0) + (*num++ - '0');
     206         while ( *num >= '0' && *num <= '9' );      /* Number? */
     207     if ( *num == '.' && num[1] >= '0' && num[1] <= '9' )
     208     {
     209         num++;  
     210         do
     211             n = (n * 10.0) + (*num++ - '0'), scale--;
     212         while ( *num >= '0' && *num <= '9' );
     213     }                      /* Fractional part? --> 小数部分 */
     214     if ( *num == 'e' || *num == 'E' )    /* Exponent?        --> 指数部分 */
     215     {
     216         num++; if ( *num == '+' )
     217             num++;
     218         else if ( *num == '-' )
     219             signsubscale = -1, num++;                       /* With sign? */
     220         while ( *num >= '0' && *num <= '9' )
     221             subscale = (subscale * 10) + (*num++ - '0');    /* Number? */
     222     }
     223 
     224     n = sign * n * pow( 10.0, (scale + subscale * signsubscale));  /* number = +/- number.fraction * 10^+/- exponent */
     225 
     226     /**
     227      * 以两种形式来保存数据,在下面的函数print_number()中输出数字的时候要比较这两个数据.
     228      */
     229     item->valuedouble    = n;
     230     item->valueint        = (int) n;
     231     item->type        = cJSON_Number;
     232     return(num);
     233 }
     234 
     235 
     236 /* Render the number nicely from the given item into a string. */
     237 /**
     238  * 下面代码中使用到DBL_EPSILON,其意思是双精度最小误差;
     239  * 请参考url: http://blog.csdn.net/x356982611/article/details/19922453
     240  */
     241 static char *print_number( cJSON *item )
     242 {
     243     /**
     244      * 局部变量说明:
     245      *     1.str : 用于指向输出的数字字符串;
     246      *     2.d   : 保存item中的double数字.
     247      */
     248     char    *str;
     249     double    d = item->valuedouble;
     250     if ( fabs( ( (double) item->valueint) - d ) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN )
     251     {
     252         str = (char *) cJSON_malloc( 21 );      /* 2^64+1 can be represented in 21 chars. */
     253         if ( str )
     254             sprintf( str, "%d", item->valueint );
     255     }else  {
     256         str = (char *) cJSON_malloc( 64 );      /* This is a nice tradeoff. */
     257         if ( str )
     258         {
     259             if ( fabs( floor( d ) - d ) <= DBL_EPSILON && fabs( d ) < 1.0e60 )
     260                 sprintf( str, "%.0f", d );
     261             else if ( fabs( d ) < 1.0e-6 || fabs( d ) > 1.0e9 )
     262                 sprintf( str, "%e", d );
     263             else sprintf( str, "%f", d );
     264         }
     265     }
     266     return(str);
     267 }
     268 
     269 
     270 static unsigned parse_hex4( const char *str )
     271 {
     272     /**
     273      * 局部变量说明:
     274      *     1.h : 保存最终返回的数据
     275      */
     276     unsigned h = 0;
     277 
     278     if ( *str >= '0' && *str <= '9' )
     279         h += (*str) - '0';
     280     else if ( *str >= 'A' && *str <= 'F' )
     281         h += 10 + (*str) - 'A';
     282     else if ( *str >= 'a' && *str <= 'f' )
     283         h += 10 + (*str) - 'a';
     284     else return(0);
     285 
     286     h = h << 4; str++;  /* h = h << 4 <===> h = h * 16 */
     287     if ( *str >= '0' && *str <= '9' )
     288         h += (*str) - '0';
     289     else if ( *str >= 'A' && *str <= 'F' )
     290         h += 10 + (*str) - 'A';
     291     else if ( *str >= 'a' && *str <= 'f' )
     292         h += 10 + (*str) - 'a';
     293     else return(0);
     294 
     295     h = h << 4; str++;
     296     if ( *str >= '0' && *str <= '9' )
     297         h += (*str) - '0';
     298     else if ( *str >= 'A' && *str <= 'F' )
     299         h += 10 + (*str) - 'A';
     300     else if ( *str >= 'a' && *str <= 'f' )
     301         h += 10 + (*str) - 'a';
     302     else return(0);
     303 
     304     h = h << 4; str++;
     305     if ( *str >= '0' && *str <= '9' )
     306         h += (*str) - '0';
     307     else if ( *str >= 'A' && *str <= 'F' )
     308         h += 10 + (*str) - 'A';
     309     else if ( *str >= 'a' && *str <= 'f' )
     310         h += 10 + (*str) - 'a';
     311     else return(0);
     312     return(h);
     313 }
     314 
     315 
     316 /* Parse the input text into an unescaped cstring, and populate item. */
     317 /* 将输入的文本分析到非转义cstring并填充item,目前不了解这里是什么情况 */
     318 /* 不清楚这里的unicode编码格式字符的处理方式 */
     319 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
     320 static const char *parse_string( cJSON *item, const char *str )
     321 {
     322     /**
     323      * 局部变量说明:
     324      *     1.ptr  : 传入参数string的指针;
     325      *     2.ptr2 : 指向输出字符串里的地址,主要用于从ptr字符串中拷贝字符到out中;
     326      *     3.out  : 指向动态分配的输出字符串的首地址;
     327      *     4.len  : 动态分配时需要的字符串的长度,分配时要在基础上+1;
     328      *     5.uc   : unicode编码格式字符; 
     329      *     6.uc2  : unicode编码格式字符.
     330      */
     331     const char *ptr = str + 1; 
     332     char *ptr2; 
     333     char *out; 
     334     int len = 0; 
     335     unsigned uc, uc2;
     336 
     337     /* 判断第一个字符是否是""",如果不是,那么就不是字符串 */
     338     if ( *str != '"' ){ ep = str; return(0); }   /* not a string! */
     339 
     340     /* 计算字符串的长度,为后面的的内存分配提供数据长度信息 */
     341     while ( *ptr != '"' && *ptr && ++len ) if ( *ptr++ == '\' )
     342         ptr++;   /* Skip escaped quotes. */
     343 
     344     out = (char *) cJSON_malloc( len + 1 ); /* This is how long we need for the string, roughly. */
     345     if ( !out )
     346         return(0);
     347 
     348     /* ptr指向'"'后面那个字符,ptr2指向out的首地址,有利于数据拷贝 */
     349     ptr = str + 1; ptr2 = out;
     350     while ( *ptr != '"' && *ptr )
     351     {
     352         if ( *ptr != '\' )
     353             *ptr2++ = *ptr++;
     354         else{
     355             ptr++;
     356             switch ( *ptr )
     357             {
     358             case 'b': *ptr2++    = ''; break;
     359             case 'f': *ptr2++    = 'f'; break;
     360             case 'n': *ptr2++    = '
    '; break;
     361             case 'r': *ptr2++    = '
    '; break;
     362             case 't': *ptr2++    = '	'; break;
     363             case 'u':                                       /* transcode utf16 to utf8. */
     364                 uc = parse_hex4( ptr + 1 ); ptr += 4;       /* get the unicode char. */
     365 
     366                 if ( (uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0 )
     367                     break;                                  /* check for invalid.    */
     368 
     369                 if ( uc >= 0xD800 && uc <= 0xDBFF )         /* UTF16 surrogate pairs.    */
     370                 {
     371                     if ( ptr[1] != '\' || ptr[2] != 'u' )
     372                         break;                  /* missing second-half of surrogate.    */
     373                     uc2 = parse_hex4( ptr + 3 ); ptr += 6;
     374                     if ( uc2 < 0xDC00 || uc2 > 0xDFFF )
     375                         break;                  /* invalid second-half of surrogate.    */
     376                     uc = 0x10000 + ( ( (uc & 0x3FF) << 10) | (uc2 & 0x3FF));
     377                 }
     378 
     379                 len = 4; if ( uc < 0x80 )
     380                     len = 1;
     381                 else if ( uc < 0x800 )
     382                     len = 2;
     383                 else if ( uc < 0x10000 )
     384                     len = 3;
     385                 ptr2 += len;
     386 
     387                 switch ( len )
     388                 {
     389                 case 4: *--ptr2 = ( (uc | 0x80) & 0xBF); uc >>= 6;
     390                 case 3: *--ptr2 = ( (uc | 0x80) & 0xBF); uc >>= 6;
     391                 case 2: *--ptr2 = ( (uc | 0x80) & 0xBF); uc >>= 6;
     392                 case 1: *--ptr2 = (uc | firstByteMark[len]);
     393                 }
     394                 ptr2 += len;
     395                 break;
     396             default:  *ptr2++ = *ptr; break;
     397             }
     398             ptr++;
     399         }
     400     }
     401     *ptr2 = 0;
     402     if ( *ptr == '"' )
     403         ptr++;
     404     item->valuestring    = out;
     405     item->type        = cJSON_String;
     406     return(ptr);
     407 }
     408 
     409 
     410 /* Render the cstring provided to an escaped version that can be printed. */
     411 static char *print_string_ptr( const char *str )
     412 {
     413     /**
     414      * 局部变量说明:
     415      *     1.ptr   : 指向参数传入的str字符串;
     416      *     2.ptr2  : 指向要输出的out字符串;
     417      *     3.out   : 输出字符串;
     418      *     4.len   : 输出字符串的长度,用于内存分配出输出字符串的空间大小;
     419      *     5.token : 字符保存中间变量.
     420      */
     421     const char *ptr; 
     422     char *ptr2, *out; 
     423     int len = 0; 
     424     unsigned char token;
     425 
     426     if ( !str )
     427         return(cJSON_strdup( "" ));
     428     /* 计算字符串需要的长度 */
     429     ptr = str;
     430     while ( (token = *ptr) && ++len )
     431     {
     432         if ( strchr( ""\f
    
    	", token ))
     433             len++;
     434         else if ( token < 32 )
     435             /** 
     436              * 除了前面列出的空白字符,其他的空白都+5的长度,
     437              * 不知道为什么,应该与unicode编码有关.
     438              * 如:
     439              *     "uxxxx",u再加4个字符就是5个字符,前面解析字符的时候是这么解析的.
     440              */
     441             len += 5; 
     442         ptr++;
     443     }
     444 
     445     out = (char *) cJSON_malloc( len + 3 );
     446     if ( !out )
     447         return(0);
     448 
     449     ptr2    = out; ptr = str;
     450     *ptr2++ = '"';
     451     while ( *ptr )
     452     {
     453         if ( (unsigned char) *ptr > 31 && *ptr != '"' && *ptr != '\' )
     454             *ptr2++ = *ptr++;
     455         else{
     456             *ptr2++ = '\';
     457             switch ( token = *ptr++ )
     458             {
     459             case '\': *ptr2++                = '\'; break;
     460             case '"': *ptr2++                = '"'; break;
     461             case '': *ptr2++                = 'b'; break;
     462             case 'f': *ptr2++                = 'f'; break;
     463             case '
    ': *ptr2++                = 'n'; break;
     464             case '
    ': *ptr2++                = 'r'; break;
     465             case '	': *ptr2++                = 't'; break;
     466             default: sprintf( ptr2, "u%04x", token ); ptr2    += 5; break; /* escape and print */
     467             }
     468         }
     469     }
     470     *ptr2++ = '"'; *ptr2++ = 0;
     471     return(out);
     472 }
     473 
     474 
     475 /* Invote print_string_ptr (which is useful) on an item. */
     476 static char *print_string( cJSON *item )
     477 {
     478     return(print_string_ptr( item->valuestring ));
     479 }
     480 
     481 
     482 /* Predeclare these prototypes. --> 提前声明这些原型 */
     483 static const char *parse_value( cJSON *item, const char *value );
     484 static char *print_value( cJSON *item, int depth, int fmt );
     485 static const char *parse_array( cJSON *item, const char *value );
     486 static char *print_array( cJSON *item, int depth, int fmt );
     487 static const char *parse_object( cJSON *item, const char *value );
     488 static char *print_object( cJSON *item, int depth, int fmt );
     489 
     490 /* Utility to jump whitespace and cr/lf --> 跳过不可见字符,这些字符都集中在ascii的前32个字符 */
     491 static const char *skip( const char *in )
     492 {
     493     while ( in && *in && (unsigned char) *in <= 32 )
     494         in++;
     495     return(in);
     496 }
     497 
     498 
     499 /* Parse an object - create a new root, and populate. --> 创建一个根,并填充 */
     500 cJSON *cJSON_ParseWithOpts( const char *value, const char **return_parse_end, int require_null_terminated )
     501 {
     502     /**
     503      * 局部变量说明:
     504      *     1.end : 当解析完整个字符串的时候,最后一个字符如果不是NULL,则代表这个输入的value字串
     505      *             可能有问题;
     506      *     2.c   : cJSON节点,也是所谓的根节点.
     507      */
     508     const char    *end    = 0;
     509     cJSON        *c    = cJSON_New_Item(); 
     510     ep = 0;
     511     if ( !c )
     512         return(0);      /* memory fail */
     513 
     514     end = parse_value( c, skip( value ));
     515     if ( !end )
     516     {
     517         cJSON_Delete( c ); return(0);
     518     }                       /* parse failure. ep is set. */
     519 
     520     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
     521     /* 检查是否是正常的JSON结束字符串 */
     522     if ( require_null_terminated )
     523     {
     524         end = skip( end ); 
     525         if ( *end )
     526         {
     527             cJSON_Delete( c ); ep = end; return(0);
     528         }
     529     }
     530     if ( return_parse_end )
     531         *return_parse_end = end;
     532     return(c);
     533 }
     534 
     535 
     536 /* Default options for cJSON_Parse, 默认不检查NULL终止符 */
     537 cJSON *cJSON_Parse( const char *value )
     538 {
     539     return(cJSON_ParseWithOpts( value, 0, 0 ));
     540 }
     541 
     542 
     543 /* Render a cJSON item/entity/structure to text. */
     544 /**
     545  * print_value中的
     546  *     第二个参数是代表JSON对象的深度;
     547  *     地三个代码中的意思是逗号分割键值对后面是否要加空格,
     548  *
     549  * 如下是第三个参数事例:
     550  *    fmt = 0 : {"zjf":1,"jfz":2,"fjz":3}或[1,2,3,4]
     551  *    fmt = 1 : {"zjf":1, "jfz":2, "fjz":3}或[1, 2, 3, 4]
     552  *
     553  * 如上,这里提供了2中选择供我们选择使用.
     554  */
     555 char *cJSON_Print( cJSON *item )
     556 {
     557     return(print_value( item, 0, 1 ));
     558 }
     559 
     560 
     561 char *cJSON_PrintUnformatted( cJSON *item )
     562 {
     563     return(print_value( item, 0, 0 ));
     564 }
     565 
     566 
     567 /* Parser core - when encountering text, process appropriately. */
     568 /**
     569  * 根据首字符的不同来决定采用哪种方式进行解析字符串
     570  */
     571 static const char *parse_value( cJSON *item, const char *value )
     572 {
     573     if ( !value )
     574         return(0);  /* Fail on null. */
     575     if ( !strncmp( value, "null", 4 )) { item->type = cJSON_NULL;  return(value + 4); }
     576     if ( !strncmp( value, "false", 5 )) { item->type = cJSON_False; return(value + 5); }
     577     if ( !strncmp( value, "true", 4 )) {
     578         item->type = cJSON_True; item->valueint = 1; return(value + 4);
     579     }
     580     if ( *value == '"' ) { return(parse_string( item, value )); }
     581     if ( *value == '-' || (*value >= '0' && *value <= '9')) { 
     582         return(parse_number( item, value )); 
     583     }
     584     if ( *value == '[' ) { return(parse_array( item, value )); }
     585     if ( *value == '{' ) { return(parse_object( item, value )); }
     586 
     587     ep = value; return(0); /* failure. */
     588 }
     589 
     590 
     591 /* Render a value to text. */
     592 /**
     593  * 根据item的类型来选这使用哪种方式进行数据的输出格式
     594  */
     595 static char *print_value( cJSON *item, int depth, int fmt )
     596 {
     597     char *out = 0;
     598     if ( !item )
     599         return(0);
     600     switch ( (item->type) & 255 )
     601     {
     602     case cJSON_NULL: out    = cJSON_strdup( "null" ); break;
     603     case cJSON_False: out    = cJSON_strdup( "false" ); break;
     604     case cJSON_True: out    = cJSON_strdup( "true" ); break;
     605     case cJSON_Number: out    = print_number( item ); break;
     606     case cJSON_String: out    = print_string( item ); break;
     607     case cJSON_Array: out    = print_array( item, depth, fmt ); break;
     608     case cJSON_Object: out    = print_object( item, depth, fmt ); break;
     609     }
     610     return(out);
     611 }
     612 
     613 
     614 /* Build an array from input text. */
     615 /**
     616  * 以以下数据为格式分析:
     617  *    [              
     618  *       [0, -1, 0],
     619  *       [1, 0, 0],
     620  *       [0, 0, 1]
     621  *    ]
     622  *
     623  *    1.先检测到[;
     624  *    2.然后skip掉换行符,空白字符;
     625  *    3.parse_value重新检测字符串,也就能再次检测又是一个数组了[0, -1, 0],
     626  *        递归进入解析[0, -1, 0],并解析出0,-1,0,保存在节点中.
     627  *    4.检测是否遇到','字符,如果遇到说明后面还有内容需要解析;
     628  *    5.循环解析接下来的内容.
     629  */
     630 static const char *parse_array( cJSON *item, const char *value )
     631 {
     632     cJSON *child;
     633     if ( *value != '[' )
     634     {
     635         ep = value; return(0);
     636     }                                                       /* not an array! */
     637 
     638     item->type    = cJSON_Array;
     639     value        = skip( value + 1 );
     640     if ( *value == ']' )
     641         return(value + 1);                              /* empty array. */
     642 
     643     item->child = child = cJSON_New_Item();
     644     if ( !item->child )
     645         return(0);                                      /* memory fail */
     646     value = skip( parse_value( child, skip( value )));    /* skip any spacing, get the value. */
     647     if ( !value )
     648         return(0);
     649 
     650     while ( *value == ',' )
     651     {
     652         cJSON *new_item;
     653         if ( !(new_item = cJSON_New_Item()))
     654             return(0);      /* memory fail */
     655         child->next    = new_item; new_item->prev = child; child = new_item;
     656         value        = skip( parse_value( child, skip( value + 1 )));
     657         if ( !value )
     658             return(0);      /* memory fail */
     659     }
     660 
     661     if ( *value == ']' )
     662         return(value + 1);      /* end of array */
     663     ep = value; return(0);          /* malformed. --> 格式不正确 */
     664 }
     665 
     666 
     667 /* Render an array to text */
     668 static char *print_array( cJSON *item, int depth, int fmt )
     669 {
     670     /**
     671      * 局部变量说明:
     672      *     1.entries    : 输出字符串数组,本来是保存在节点中的,被提取取来报存在字符串数组中;
     673      *     2.out        : 合并entries字符数组中的字符串,得到out;
     674      *     3.ptr        : 指向out的指针;
     675      *     4.ret        : 函数执行结果的返回值;
     676      *     5.len        : 用于统计总的字符长度;
     677      *     6.child      : 用于指向当前正要处理的节点;
     678      *     7.numentries : 用于统计总共有多少个entries;
     679      *     8.i          : for循环计数;
     680      *     9.fail       : 处理出错标志.
     681      */
     682     char    **entries;
     683     char    *out    = 0, *ptr, *ret; 
     684     int     len     = 5;
     685     cJSON    *child    = item->child;
     686     int    numentries    = 0 /*number entries*/, i = 0, fail = 0;
     687 
     688     /* How many entries in the array? */
     689     while ( child )
     690         numentries++, child = child->next;
     691     /* Explicitly handle numentries==0 --> 显示处理条目为0的情况 */
     692     if ( !numentries )
     693     {
     694         out = (char *) cJSON_malloc( 3 );
     695         if ( out )
     696             strcpy( out, "[]" );
     697         return(out);
     698     }
     699     /* Allocate an array to hold the values for each */
     700     entries = (char * *) cJSON_malloc( numentries * sizeof(char*));
     701     if ( !entries )
     702         return(0);
     703     memset( entries, 0, numentries * sizeof(char*));
     704     /* Retrieve all the results: --> 恢复结果 */
     705     child = item->child;
     706     while ( child && !fail )
     707     {
     708         ret    = print_value( child, depth + 1, fmt );
     709         entries[i++] = ret;
     710         if ( ret )
     711             /**
     712              * 为什么要加2,目前只发现需要加1就够了,因为就加了一个逗号.
     713              * 不知何故........
     714              * 难道是为了给那对[]留下空间?
     715              */
     716             len += strlen( ret ) + 2 + (fmt ? 1 : 0); 
     717         else fail = 1;
     718         child = child->next;
     719     }
     720 
     721     /* If we didn't fail, try to malloc the output string */
     722     if ( !fail )
     723         out = (char *) cJSON_malloc( len );
     724     /* If that fails, we fail. */
     725     if ( !out )
     726         fail = 1;
     727 
     728     /* Handle failure. */
     729     if ( fail )
     730     {
     731         for ( i = 0; i < numentries; i++ )
     732             if ( entries[i] )
     733                 cJSON_free( entries[i] );
     734         cJSON_free( entries );
     735         return(0);
     736     }
     737 
     738     /* Compose the output array. --> 合成输出数组 */
     739     *out    = '[';
     740     ptr    = out + 1; *ptr = 0;
     741     for ( i = 0; i < numentries; i++ )
     742     {
     743         strcpy( ptr, entries[i] ); ptr += strlen( entries[i] );
     744         if ( i != numentries - 1 )
     745         {
     746             *ptr++    = ',';            /* 字符和分割符 */
     747             if ( fmt ) *ptr++ = ' ';  /* 一个格式字符 */
     748             *ptr    = 0;              /* 每次都结束当前字符串,但是运行后续代码,又会被取代 */
     749         }
     750         cJSON_free( entries[i] );
     751     }
     752     cJSON_free( entries );
     753     *ptr++ = ']'; *ptr++ = 0;
     754     return(out);
     755 }
     756 
     757 
     758 /* Build an object from the text. */
     759 /**
     760  * 以下数据为格式分析:
     761  *     {
     762  *         "name": "Jack ("Bee") Nimble", 
     763  *         "format": {
     764  *             "type":       "rect", 
     765  *             "width":      1920, 
     766  *             "height":     1080, 
     767  *             "interlace":  false, 
     768  *             "frame rate": 24
     769  *         }
     770  *     }
     771  * 
     772  *     1.检测到'{';
     773  *     2.跳过空白字符,换行符;
     774  *     3.通过parse_string获取name;
     775  *     4.判断键值对标识符':';
     776  *     5.通过parse_value获取对应的value;
     777  *     6.parse_value和前面的几个函数一样,是递归函数;
     778  *     7.通过while循环解析剩下的键值对.
     779  */
     780 static const char *parse_object( cJSON *item, const char *value )
     781 {
     782     cJSON *child;
     783     if ( *value != '{' )
     784     {
     785         ep = value; return(0);
     786     }                               /* not an object! */
     787 
     788     item->type    = cJSON_Object;
     789     value        = skip( value + 1 );
     790     if ( *value == '}' )
     791         return(value + 1);      /* empty array. */
     792 
     793     item->child = child = cJSON_New_Item();
     794     if ( !item->child )
     795         return(0);
     796     value = skip( parse_string( child, skip( value )));
     797     if ( !value )
     798         return(0);
     799     child->string = child->valuestring; child->valuestring = 0;
     800     if ( *value != ':' )
     801     {
     802         ep = value; return(0);
     803     }                                                               /* fail! */
     804     value = skip( parse_value( child, skip( value + 1 )));        /* skip any spacing, get the value. */
     805     if ( !value )
     806         return(0);
     807 
     808     while ( *value == ',' )
     809     {
     810         cJSON *new_item;
     811         if ( !(new_item = cJSON_New_Item()))
     812             return(0);            /* memory fail */
     813         child->next    = new_item; new_item->prev = child; child = new_item;
     814         value        = skip( parse_string( child, skip( value + 1 )));
     815         if ( !value )
     816             return(0);
     817         child->string = child->valuestring; child->valuestring = 0;
     818         if ( *value != ':' )
     819         {
     820             ep = value; return(0);
     821         }                                                               /* fail! */
     822         value = skip( parse_value( child, skip( value + 1 )));        /* skip any spacing, get the value. */
     823         if ( !value )
     824             return(0);
     825     }
     826 
     827     if ( *value == '}' )
     828         return(value + 1);                                              /* end of array */
     829     ep = value; return(0);                                                  /* malformed. */
     830 }
     831 
     832 
     833 /* Render an object to text. */
     834 /* 该函数和前面的print_array()相似 */
     835 static char *print_object( cJSON *item, int depth, int fmt )
     836 {
     837     /**
     838      * 局部变量说明:
     839      *     1.entries : 键值对的value;
     840      *     2.names   : 键值对的key;
     841      *     3.out     : 指向输出的字符串;
     842      *     4.ptr     : 指向out输出的字符串;
     843      *     5.ret     : 执行函数时返回的字符串地址;
     844      *     6.str     : 执行函数返回的字符串的地址;
     845      *     7.len     : 字符串的长度;
     846      *     8.i       : for循环用于计数的变量;
     847      *     9.j       : for循环用于计数的变量;
     848      *     10.child  : 指向节点的指针;
     849      *     11.fail   : 输出出错时的标志;
     850      *     12.numentries : 用于统计当前结构深度层次上的节点个数
     851      */
     852     char **entries = 0, **names = 0;
     853     char *out = 0, *ptr, *ret, *str; 
     854     int len = 7, i = 0, j;
     855     cJSON *child = item->child;
     856     int    numentries = 0, fail = 0;
     857     /* Count the number of entries. */
     858     while ( child )
     859         numentries++, child = child->next;
     860     /* Explicitly handle empty object case */
     861     if ( !numentries )
     862     {
     863         out = (char *) cJSON_malloc( fmt ? depth + 4 : 3 );
     864         if ( !out )
     865             return(0);
     866         ptr = out; *ptr++ = '{';
     867         if ( fmt )
     868         {
     869             *ptr++ = '
    '; 
     870             for ( i = 0; i < depth - 1; i++ )
     871                 *ptr++ = '	';
     872         }
     873         *ptr++ = '}'; *ptr++ = 0;
     874         return(out);
     875     }
     876     /* Allocate space for the names and the objects */
     877     entries = (char **) cJSON_malloc( numentries * sizeof(char*));
     878     if ( !entries )
     879         return(0);
     880     names = (char **) cJSON_malloc( numentries * sizeof(char*));
     881     if ( !names )
     882     {
     883         cJSON_free( entries ); return(0);
     884     }
     885     memset( entries, 0, sizeof(char*) * numentries );
     886     memset( names, 0, sizeof(char*) * numentries );
     887 
     888     /* Collect all the results into our arrays: */
     889     child = item->child; depth++; if ( fmt )
     890         len += depth;
     891     while ( child )
     892     {
     893         names[i]    = str = print_string_ptr( child->string );
     894         entries[i++]    = ret = print_value( child, depth, fmt );
     895         if ( str && ret )
     896             len += strlen( ret ) + strlen( str ) + 2 + (fmt ? 2 + depth : 0);
     897         else fail = 1;
     898         child = child->next;
     899     }
     900 
     901     /* Try to allocate the output string */
     902     if ( !fail )
     903         out = (char *) cJSON_malloc( len );
     904     if ( !out )
     905         fail = 1;
     906 
     907     /* Handle failure */
     908     if ( fail )
     909     {
     910         for ( i = 0; i < numentries; i++ )
     911         {
     912             if ( names[i] )
     913                 cJSON_free( names[i] );
     914             if ( entries[i] )
     915                 cJSON_free( entries[i] );
     916         }
     917         cJSON_free( names ); cJSON_free( entries );
     918         return(0);
     919     }
     920 
     921     /* Compose the output: */
     922     *out    = '{'; 
     923     ptr = out + 1; 
     924     if ( fmt )
     925         *ptr++ = '
    ';
     926     *ptr    = 0;
     927     for ( i = 0; i < numentries; i++ )
     928     {
     929         if ( fmt )
     930             for ( j = 0; j < depth; j++ )
     931                 *ptr++ = '	';
     932         strcpy( ptr, names[i] ); 
     933         ptr    += strlen( names[i] );
     934         *ptr++ = ':'; 
     935         if ( fmt )
     936             *ptr++ = '	';
     937         strcpy( ptr, entries[i] ); 
     938         ptr    += strlen( entries[i] );
     939         if ( i != numentries - 1 )
     940             *ptr++ = ',';
     941         if ( fmt )
     942             *ptr++ = '
    ';
     943         *ptr = 0;
     944         cJSON_free( names[i] ); 
     945         cJSON_free( entries[i] );
     946     }
     947 
     948     cJSON_free( names ); 
     949     cJSON_free( entries );
     950     if ( fmt )
     951         for ( i = 0; i < depth - 1; i++ )
     952             *ptr++ = '	';
     953     *ptr++ = '}'; 
     954     *ptr++ = 0;
     955     return(out);
     956 }
     957 
     958 
     959 /* Get Array size/item / object item. */
     960 int cJSON_GetArraySize( cJSON *array )
     961 {
     962     cJSON *c = array->child; int i = 0; while ( c )
     963         i++, c = c->next;
     964     return(i);
     965 }
     966 
     967 
     968 cJSON *cJSON_GetArrayItem( cJSON *array, int item )
     969 {
     970     cJSON *c = array->child;  while ( c && item > 0 )
     971         item--, c = c->next;
     972     return(c);
     973 }
     974 
     975 
     976 cJSON *cJSON_GetObjectItem( cJSON *object, const char *string )
     977 {
     978     cJSON *c = object->child; while ( c && cJSON_strcasecmp( c->string, string ))
     979         c = c->next;
     980     return(c);
     981 }
     982 
     983 
     984 /* Utility for array list handling. --> 在当前节点的后面添加一个节点 */
     985 static void suffix_object( cJSON *prev, cJSON *item )
     986 {
     987     prev->next = item; item->prev = prev;
     988 }
     989 
     990 
     991 /* Utility for handling references. */
     992 static cJSON *create_reference( cJSON *item )
     993 {
     994     cJSON *ref = cJSON_New_Item(); 
     995     if ( !ref )
     996         return(0);
     997     memcpy( ref, item, sizeof(cJSON)); 
     998     ref->string = 0; 
     999     ref->type |= cJSON_IsReference; 
    1000     ref->next = ref->prev = 0; 
    1001     return(ref);
    1002 }
    1003 
    1004 
    1005 /* Add item to array/object. */
    1006 void   cJSON_AddItemToArray( cJSON *array, cJSON *item )
    1007 {
    1008     cJSON *c = array->child; 
    1009     if ( !item )
    1010         return;
    1011     if ( !c )
    1012     {
    1013         array->child = item;
    1014     } 
    1015     else 
    1016     { 
    1017         while ( c && c->next )
    1018              c = c->next;
    1019         suffix_object( c, item ); 
    1020     }
    1021 }
    1022 
    1023 
    1024 void   cJSON_AddItemToObject( cJSON *object, const char *string, cJSON *item )
    1025 {
    1026     if ( !item )
    1027         return;
    1028     if ( item->string )
    1029         cJSON_free( item->string );
    1030     item->string = cJSON_strdup( string ); 
    1031     cJSON_AddItemToArray( object, item );
    1032 }
    1033 
    1034 
    1035 void cJSON_AddItemReferenceToArray( cJSON *array, cJSON *item )
    1036 {
    1037     cJSON_AddItemToArray( array, create_reference( item ));
    1038 }
    1039 
    1040 
    1041 void cJSON_AddItemReferenceToObject( cJSON *object, const char *string, cJSON *item )
    1042 {
    1043     cJSON_AddItemToObject( object, string, create_reference( item ));
    1044 }
    1045 
    1046 
    1047 cJSON *cJSON_DetachItemFromArray( cJSON *array, int which )
    1048 {
    1049     cJSON *c = array->child; 
    1050     while ( c && which > 0 )
    1051         c = c->next, which--;
    1052 
    1053     if ( !c )
    1054         return(0);
    1055     if ( c->prev )
    1056         c->prev->next = c->next;
    1057     if ( c->next )
    1058         c->next->prev = c->prev;
    1059     if ( c == array->child )
    1060         array->child = c->next;
    1061     c->prev = c->next = 0; 
    1062     return(c);
    1063 }
    1064 
    1065 
    1066 void   cJSON_DeleteItemFromArray( cJSON *array, int which )
    1067 {
    1068     cJSON_Delete( cJSON_DetachItemFromArray( array, which ));
    1069 }
    1070 
    1071 
    1072 cJSON *cJSON_DetachItemFromObject( cJSON *object, const char *string )
    1073 {
    1074     int i = 0; cJSON *c = object->child; 
    1075     while ( c && cJSON_strcasecmp( c->string, string ))
    1076         i++, c = c->next;
    1077     if ( c )
    1078         return(cJSON_DetachItemFromArray( object, i ));
    1079     return(0);
    1080 }
    1081 
    1082 
    1083 void cJSON_DeleteItemFromObject( cJSON *object, const char *string )
    1084 {
    1085     cJSON_Delete( cJSON_DetachItemFromObject( object, string ));
    1086 }
    1087 
    1088 
    1089 /* Replace array/object items with new ones. */
    1090 void cJSON_ReplaceItemInArray( cJSON *array, int which, cJSON *newitem )
    1091 {
    1092     cJSON *c = array->child; 
    1093     while ( c && which > 0 )
    1094         c = c->next, which--;
    1095     if ( !c )
    1096         return;
    1097     newitem->next = c->next; 
    1098     newitem->prev = c->prev; 
    1099     if ( newitem->next )
    1100         newitem->next->prev = newitem;
    1101     if ( c == array->child )
    1102         array->child = newitem;
    1103     else 
    1104         newitem->prev->next = newitem; 
    1105     c->next = c->prev = 0; 
    1106     cJSON_Delete( c );
    1107 }
    1108 
    1109 
    1110 void cJSON_ReplaceItemInObject( cJSON *object, const char *string, cJSON *newitem )
    1111 {
    1112     int i = 0; 
    1113     cJSON *c = object->child; 
    1114     while ( c && cJSON_strcasecmp( c->string, string ))
    1115         i++, c = c->next;
    1116     if ( c )
    1117     {
    1118         newitem->string = cJSON_strdup( string ); 
    1119         cJSON_ReplaceItemInArray( object, i, newitem );
    1120     }
    1121 }
    1122 
    1123 
    1124 /* Create basic types: */
    1125 cJSON *cJSON_CreateNull( void )
    1126 {
    1127     cJSON *item = cJSON_New_Item(); 
    1128     if ( item )
    1129         item->type = cJSON_NULL;
    1130     return(item);
    1131 }
    1132 
    1133 
    1134 cJSON *cJSON_CreateTrue( void )
    1135 {
    1136     cJSON *item = cJSON_New_Item(); 
    1137     if ( item )
    1138         item->type = cJSON_True;
    1139     return(item);
    1140 }
    1141 
    1142 
    1143 cJSON *cJSON_CreateFalse( void )
    1144 {
    1145     cJSON *item = cJSON_New_Item(); 
    1146     if ( item )
    1147         item->type = cJSON_False;
    1148     return(item);
    1149 }
    1150 
    1151 
    1152 cJSON *cJSON_CreateBool( int b )
    1153 {
    1154     cJSON *item = cJSON_New_Item(); 
    1155     if ( item )
    1156         item->type = b ? cJSON_True : cJSON_False;
    1157     return(item);
    1158 }
    1159 
    1160 
    1161 cJSON *cJSON_CreateNumber( double num )
    1162 {
    1163     cJSON *item = cJSON_New_Item(); 
    1164     if ( item )
    1165     {
    1166         item->type = cJSON_Number; 
    1167         item->valuedouble = num; 
    1168         item->valueint = (int) num;
    1169     }
    1170     return(item);
    1171 }
    1172 
    1173 
    1174 cJSON *cJSON_CreateString( const char *string )
    1175 {
    1176     cJSON *item = cJSON_New_Item(); 
    1177     if ( item )
    1178     {
    1179         item->type = cJSON_String; 
    1180         item->valuestring = cJSON_strdup( string );
    1181     }
    1182     return(item);
    1183 }
    1184 
    1185 
    1186 cJSON *cJSON_CreateArray( void )
    1187 {
    1188     cJSON *item = cJSON_New_Item(); 
    1189     if ( item )
    1190         item->type = cJSON_Array;
    1191     return(item);
    1192 }
    1193 
    1194 
    1195 cJSON *cJSON_CreateObject( void )
    1196 {
    1197     cJSON *item = cJSON_New_Item(); 
    1198     if ( item )
    1199         item->type = cJSON_Object;
    1200     return(item);
    1201 }
    1202 
    1203 
    1204 /* Create Arrays: */
    1205 cJSON *cJSON_CreateIntArray( const int *numbers, int count )
    1206 {
    1207     int i; 
    1208     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); 
    1209     for ( i = 0; a && i < count; i++ )
    1210     {
    1211         n = cJSON_CreateNumber( numbers[i] ); 
    1212         if ( !i )
    1213             a->child = n;
    1214         else 
    1215             suffix_object( p, n ); 
    1216         p = n;
    1217     }
    1218     return(a);
    1219 }
    1220 
    1221 
    1222 cJSON *cJSON_CreateFloatArray( const float *numbers, int count )
    1223 {
    1224     int i; 
    1225     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); 
    1226     for ( i = 0; a && i < count; i++ )
    1227     {
    1228         n = cJSON_CreateNumber( numbers[i] );
    1229         if ( !i )
    1230             a->child = n;
    1231         else 
    1232             suffix_object( p, n );
    1233         p = n;
    1234     }
    1235     return(a);
    1236 }
    1237 
    1238 
    1239 cJSON *cJSON_CreateDoubleArray( const double *numbers, int count )
    1240 {
    1241     int i; 
    1242     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); 
    1243     for ( i = 0; a && i < count; i++ )
    1244     {
    1245         n = cJSON_CreateNumber( numbers[i] );
    1246         if ( !i )
    1247             a->child = n;
    1248         else 
    1249             suffix_object( p, n );
    1250         p = n;
    1251     }
    1252     return(a);
    1253 }
    1254 
    1255 
    1256 cJSON *cJSON_CreateStringArray( const char **strings, int count )
    1257 {
    1258     int i; cJSON *n = 0, *p = 0, *a = cJSON_CreateArray(); 
    1259     for ( i = 0; a && i < count; i++ )
    1260     {
    1261         n = cJSON_CreateString( strings[i] );
    1262         if ( !i )
    1263             a->child = n;
    1264         else 
    1265             suffix_object( p, n );
    1266             p = n;
    1267     }
    1268     return(a);
    1269 }
    1270 
    1271 
    1272 /* Duplication */
    1273 cJSON *cJSON_Duplicate( cJSON *item, int recurse )
    1274 {
    1275     cJSON *newitem, *cptr, *nptr = 0, *newchild;
    1276     /* Bail on bad ptr */
    1277     if ( !item )
    1278         return(0);
    1279     /* Create new item */
    1280     newitem = cJSON_New_Item();
    1281     if ( !newitem )
    1282         return(0);
    1283     /* Copy over all vars */
    1284     newitem->type = item->type & (~cJSON_IsReference), newitem->valueint = item->valueint, newitem->valuedouble = item->valuedouble;
    1285     if ( item->valuestring )
    1286     {
    1287         newitem->valuestring = cJSON_strdup( item->valuestring ); if ( !newitem->valuestring )
    1288         {
    1289             cJSON_Delete( newitem ); return(0);
    1290         }
    1291     }
    1292     if ( item->string )
    1293     {
    1294         newitem->string = cJSON_strdup( item->string );   if ( !newitem->string )
    1295         {
    1296             cJSON_Delete( newitem ); return(0);
    1297         }
    1298     }
    1299     /* If non-recursive, then we're done! */
    1300     if ( !recurse )
    1301         return(newitem);
    1302     /* Walk the ->next chain for the child. */
    1303     cptr = item->child;
    1304     while ( cptr )
    1305     {
    1306         newchild = cJSON_Duplicate( cptr, 1 ); /* Duplicate (with recurse) each item in the ->next chain */
    1307         if ( !newchild )
    1308         {
    1309             cJSON_Delete( newitem ); return(0);
    1310         }
    1311         if ( nptr )
    1312         {
    1313             nptr->next = newchild, newchild->prev = nptr; nptr = newchild;
    1314         }                                                    /* If newitem->child already set, then crosswire ->prev and ->next and move on */
    1315         else { newitem->child = newchild; nptr = newchild; } /* Set newitem->child and move to it */
    1316         cptr = cptr->next;
    1317     }
    1318     return(newitem);
    1319 }
    1320 
    1321 
    1322 void cJSON_Minify( char *json )
    1323 {
    1324     char *into = json;
    1325     while ( *json )
    1326     {
    1327         if ( *json == ' ' )
    1328             json++;
    1329         else if ( *json == '	' )
    1330             json++;  /* Whitespace characters. */
    1331         else if ( *json == '
    ' )
    1332             json++;
    1333         else if ( *json == '
    ' )
    1334             json++;
    1335         else if ( *json == '/' && json[1] == '/' )
    1336             while ( *json && *json != '
    ' )
    1337                 json++;
    1338                 /* double-slash comments, to end of line. */
    1339         else if ( *json == '/' && json[1] == '*' )
    1340         {
    1341             while ( *json && !(*json == '*' && json[1] == '/'))
    1342                 json++;
    1343             json += 2;
    1344         }       /* multiline comments. */
    1345         else if ( *json == '"' )
    1346         {
    1347             *into++ = *json++; while ( *json && *json != '"' )
    1348             {
    1349                 if ( *json == '\' )
    1350                     *into++ = *json++;
    1351                 *into++ = *json++;
    1352             }
    1353             *into++ = *json++;
    1354         }                               /* string literals, which are " sensitive. */
    1355         else *into++ = *json++;         /* All other characters. */
    1356     }
    1357     *into = 0;                              /* and null-terminate. */
    1358 }
  • 相关阅读:
    《2019年软件工程助教培训计划》
    地铁线路项目-结对编程
    预培训-个人项目(地铁线路规划)
    粗读《构建之法》后的问题
    netapp 修改IP地址
    jump server 2.6.1 安装与配置
    CCNA-实验1-Manage_IOS
    系统结构综合实践期末大作业 第22组
    2017级系统综合实践第7次实践作业 01组
    2017级系统综合实践第6次实践作业 01组
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/4314330.html
Copyright © 2011-2022 走看看