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++    = '\b'; break;
 359             case 'f': *ptr2++    = '\f'; break;
 360             case 'n': *ptr2++    = '\n'; break;
 361             case 'r': *ptr2++    = '\r'; break;
 362             case 't': *ptr2++    = '\t'; 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( "\"\\\b\f\n\r\t", 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 '\b': *ptr2++                = 'b'; break;
 462             case '\f': *ptr2++                = 'f'; break;
 463             case '\n': *ptr2++                = 'n'; break;
 464             case '\r': *ptr2++                = 'r'; break;
 465             case '\t': *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++ = '\n'; 
 870             for ( i = 0; i < depth - 1; i++ )
 871                 *ptr++ = '\t';
 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++ = '\n';
 926     *ptr    = 0;
 927     for ( i = 0; i < numentries; i++ )
 928     {
 929         if ( fmt )
 930             for ( j = 0; j < depth; j++ )
 931                 *ptr++ = '\t';
 932         strcpy( ptr, names[i] ); 
 933         ptr    += strlen( names[i] );
 934         *ptr++ = ':'; 
 935         if ( fmt )
 936             *ptr++ = '\t';
 937         strcpy( ptr, entries[i] ); 
 938         ptr    += strlen( entries[i] );
 939         if ( i != numentries - 1 )
 940             *ptr++ = ',';
 941         if ( fmt )
 942             *ptr++ = '\n';
 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++ = '\t';
 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 == '\t' )
1330             json++;  /* Whitespace characters. */
1331         else if ( *json == '\r' )
1332             json++;
1333         else if ( *json == '\n' )
1334             json++;
1335         else if ( *json == '/' && json[1] == '/' )
1336             while ( *json && *json != '\n' )
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 }

 

上一篇:阿里云突发性能T5实例与全新T6实例和有什么区别?


下一篇:Redis不同数据类型的的数据结构实现