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 }