【轉】 cJSON 源碼解析

關於cjson的介紹和使用方法就不在這裏介紹了,詳情請查看上一篇博客cjson使用方法node

JSON的內存結構像廣義表,能夠認爲是有層次的雙向鏈表。
linux

 

cJSON程序中的細節點以下:json

  • 大量宏替換
  • 大量靜態函數
  • 錯誤處理機制
  • 字符串處理時存在utf16轉utf9,編碼轉換
  • 用函數指針封裝malloc,free,方便用於處理,好比在申請後初始化,或者釋放前進行一些處理等。

cJSON中的重要接口函數以下:數組

 

解析函數 cJSON * cJSON_Parse(const char *value); 打印函數 char * cJSON_Print(cJSON * item); 刪除函數 void cJSON_Delete(cJSON * c); 構造函數 create系列和add系列 解析字符串 char *parse_string(cJSON*item,const char *str) 解析數字 char *parse_number(cJSON *item,const char *num) 解析數組 char *parse_array(cJSON *item,const char *value) 解析對象 char *parse_object(cJSON *item,const char *value) ......

 

cjosn有兩個相關的文件,一個cJSON.c和cJSON.h。咱們先從頭文件開始分析。緩存

首先,咱們會看到頭文件的開頭和結尾這樣的語句:app

 

  1. #ifndef cJSON__h  
  2. #define cJSON__h  
  3.   
  4. #ifdef __cplusplus  
  5. extern "C"  
  6. {  
  7. #endif 

...函數

...ui

  1. #ifdef __cplusplus  
  2. }  
  3. #endif  
  4.   
  5. #endif  




#ifndef cJSON_h,#define cJSON_h,#endif . 這是爲了防止頭文件被重複引用。編碼

extern "C"的主要做用就是爲了可以正確實現C++代碼調用其餘C語言代碼。加上extern "C"後,會指示編譯器這部分代碼按C語言的進行編譯,而不是C++的。因爲C++支持函數重載,所以編譯器編譯函數的過程當中會將函數的參數類型也加到編譯後的代碼中,而不只僅是函數名;而C語言並不支持函數重載,所以編譯C語言代碼的函數時不會帶上函數的參數類型,通常之包括函數名。spa


接着往下看,就會看到cjson的結構體的定義,cjson對象存儲結構實際是一個結構體。

  1. // JSON的一個value的結構體  
  2. typedef struct cJSON  
  3. {  
  4.     struct cJSON *next,*prev;    // 同一級的元素使用雙向列表存儲  
  5.     struct cJSON *child;           // 若是是一個object或array的話,child爲第一個兒子的指針  
  6.   
  7.     int type;                            // value的類型  
  8.   
  9.     char *valuestring;             // 若是這個value是字符串類型,則此處爲字符串值  
  10.     int valueint;                      // 若是是數字的話,整數值  
  11.     double valuedouble;            // 若是是數字的話,讀點數值  
  12.   
  13.     char *string;                      // json對象的名稱  
  14. } cJSON;  






前面提到過,cjson的存儲結構像一個廣義表,其實也能夠說是一個樹,不過兄弟結點之間都經過prev和next兩個指針鏈接起來。

prev和next分別是cjson對象的前驅和後繼,屬於同一級別的對象。chid則指向孩子結點,而且是第一個孩子的指針。


示例圖以下:



cjson的類型宏定義:

  1. /* cJSON Types: */  
  2. #define cJSON_False  (1 << 0)  
  3. #define cJSON_True   (1 << 1)  
  4. #define cJSON_NULL   (1 << 2)  
  5. #define cJSON_Number (1 << 3)  
  6. #define cJSON_String (1 << 4)  
  7. #define cJSON_Array  (1 << 5)  
  8. #define cJSON_Object (1 << 6)  
  9.       
  10. #define cJSON_IsReference 256  
  11. #define cJSON_StringIsConst 512  


這些宏定義是對結構體type的值定義,處理時只須要將type的值&255進行位運算,便可獲得json裏儲存的數據類型。


cjson的建立:

cjson的建立的過程就是建立一個cjson結構體,再經過add一系列函數將其餘孩子結點數據或同等級結點加入,將相關結點經過指針鏈起來。

cjson_create一系列函數:cJSON_CreateArray(),cJSON_CreateObject(),cJSON_CreateString()等函數,都是調用cJSON_New_Item()函數建立對應節點信息。函數返回一個json結構體指針。

相關函數以下:

  1. static cJSON *cJSON_New_Item(void)   //建立json結構體  
  2. {  
  3.     cJSON *node = (cJSON *) cJSON_malloc(sizeof(cJSON));  
  4.   
  5.     if (node)  
  6.         memset(node, 0, sizeof(cJSON));   //初始化結構體  
  7.     return node;  
  8. }  
  9. cJSON *cJSON_CreateNull(void)  
  10. {  
  11.     cJSON *item = cJSON_New_Item();  
  12.   
  13.     if (item)  
  14.         item->type = cJSON_NULL;  
  15.     return item;  
  16. }  
  17.   
  18. cJSON *cJSON_CreateTrue(void)  
  19. {  
  20.     cJSON *item = cJSON_New_Item();  
  21.   
  22.     if (item)  
  23.         item->type = cJSON_True;  
  24.     return item;  
  25. }  
  26.   
  27. cJSON *cJSON_CreateFalse(void)  
  28. {  
  29.     cJSON *item = cJSON_New_Item();  
  30.   
  31.     if (item)  
  32.         item->type = cJSON_False;  
  33.     return item;  
  34. }  
  35.   
  36. cJSON *cJSON_CreateBool(int b)  
  37. {  
  38.     cJSON *item = cJSON_New_Item();  
  39.   
  40.     if (item)  
  41.         item->type = b ? cJSON_True : cJSON_False;  
  42.     return item;  
  43. }  
  44.   
  45. cJSON *cJSON_CreateNumber(double num)  
  46. {  
  47.     cJSON *item = cJSON_New_Item();  
  48.   
  49.     if (item) {  
  50.         item->type = cJSON_Number;  
  51.         item->valuedouble = num;  
  52.         item->valueint = (int) num;  
  53.     }  
  54.     return item;  
  55. }  
  56.   
  57. cJSON *cJSON_CreateString(const char *string)  
  58. {  
  59.     cJSON *item = cJSON_New_Item();  
  60.   
  61.     if (item) {  
  62.         item->type = cJSON_String;  
  63.         item->valuestring = cJSON_strdup(string);  
  64.     }  
  65.     return item;  
  66. }  
  67.   
  68. cJSON *cJSON_CreateArray(void)  
  69. {  
  70.     cJSON *item = cJSON_New_Item();  
  71.   
  72.     if (item)  
  73.         item->type = cJSON_Array;  
  74.     return item;  
  75. }  
  76.   
  77. cJSON *cJSON_CreateObject(void)  
  78. {  
  79.     cJSON *item = cJSON_New_Item();  
  80.   
  81.     if (item)  
  82.         item->type = cJSON_Object;  
  83.     return item;  
  84. }  


建立完一個根結點結構體後,接下來就是向根結點中加入元素。

從頭文件咱們發現,

  • // 建立一個string值爲name的cJSON_Null節點,並添加到object  
  • #define cJSON_AddNullToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateNull())  
  • // 建立一個string值爲name的cJSON_True節點,並添加到object  
  • #define cJSON_AddTrueToObject(object,name)      cJSON_AddItemToObject(object, name, cJSON_CreateTrue())  
  • // 建立一個string值爲name的cJSON_False節點,並添加到object  
  • #define cJSON_AddFalseToObject(object,name)     cJSON_AddItemToObject(object, name, cJSON_CreateFalse())  
  • // 建立一個string值爲name的cJSON_CreateBool節點,並添加到object。b非0爲cJSON_True,0爲cJSON_False。  
  • #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))  
  • // 建立一個string值爲name,valuedouble爲n,valueint爲(int)n的cJSON_Number節點,並添加到object。  
  • #define cJSON_AddNumberToObject(object,name,n)  cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))  
  • // 建立一個string值爲name,valuestring爲s的cJSON_String節點,並添加到object。  
  • #define cJSON_AddStringToObject(object,name,s)  cJSON_AddItemToObject(object, name, cJSON_CreateString(s))  


過程是調用cJSON_AddItemToObject()並結合不一樣的對象類型增長節點名稱和子節點。而後在其中調用cJSON_AddItemToArray()函數來添加信息,此函數中判斷對象孩子結點是否爲NULL,若是是NULL,則直接插入,不然找到最後一個孩子,調用suffix_object()函數添加到雙向鏈表的尾部。

示例圖以下:



相關代碼以下:

  1. // 將字符串添加進對象  
  2. void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)  
  3. {  
  4.     if (!item)  
  5.      return;  
  6.     if (item->string)  
  7.         cJSON_free(item->string);         // 這個兒子以前有key,先清理  
  8.     item->string=cJSON_strdup(string);    // 設置key值  
  9.     cJSON_AddItemToArray(object,item);    // 添加兒子  
  10. }  
  11.   
  12. // 將傳入的字符串複製一副本並返回新的字符串指針  
  13. static char* cJSON_strdup(const char* str)  
  14. {  
  15.       size_t len;  
  16.       char* copy;  
  17.   
  18.       len = strlen(str) + 1;  
  19.             // 分配空間  
  20.       if (!(copy = (char*)cJSON_malloc(len)))  
  21.                 return 0;  
  22.             // 執行復制操做  
  23.       memcpy(copy,str,len);  
  24.             // 返回複製的副本  
  25.       return copy;  
  26. }  
  27.   
  28. // 添加節點到object或array中  
  29. void cJSON_AddItemToArray(cJSON *array, cJSON *item)  
  30. {  
  31.     cJSON *c=array->child;  
  32.     if (!item)  
  33.         return;  
  34.     if (!c)  
  35.     {  
  36.         array->child=item;     // 以前不存在兒子節點,直接添加  
  37.     }  
  38.     else  
  39.     {  
  40.         while (c && c->next)   // 先找到最後一個兒子  
  41.             c=c->next;  
  42.         suffix_object(c,item); // 添加兒子,c是item的兄弟節點  
  43.     }  
  44. }  
  45.   
  46. // array的處理  
  47. static void suffix_object(cJSON *prev,cJSON *item)  
  48. {  
  49.     // 兩個兄弟的指針互相指向對方  
  50.     prev->next=item;  
  51.     item->prev=prev;  
  52. }  

cjson打印:

cjson打印就是從根對象的結構體開始遍歷,獲得每一個item結點的名稱和數據,並通過處理成特定的cjson字符串的輸出形式。

cJSON_Print(root)和cJSON_PrintUnformatted(root) 函數都是打印成json字符串的函數,二者的區別就是

cJSON_PrintUnformatted(root) 處理成的字符串裏沒有\t\n這類的格式,咱們在這裏以分析cJSON_Print(root)函數

爲例,進行分析。


相關函數結構圖以下:




相關函數以下:

  1. typedef struct {  
  2.     char *buffer;  
  3.     int length;  
  4.     int offset;  
  5. } printbuffer;  
  6.   
  7.   
  8.   
  9. static int pow2gt(int x)        /*返回 一個比x的n(其中n是2的冪),而且是最小的冪,說白了就是將一個數後邊全部的位都置1而後再+1*/  
  10. {  
  11.     --x;  
  12.     x |= x >> 1;  
  13.     x |= x >> 2;  
  14.     x |= x >> 4;  
  15.     x |= x >> 8;  
  16.     x |= x >> 16;  
  17.     return x + 1;  
  18. }  
  19.   
  20. /* ensure 函數 是一個 協助 printbuffer 分配內存的一個函數   
  21.  * len 表示當前字符串的字符串起始偏移量 即 newbuffer+p->offset 起始的 
  22.  */  
  23.   
  24. static char* ensure(printbuffer *p,int needed)  
  25. {  
  26.     char *newbuffer;int newsize;  
  27.     if (!p || !p->buffer) return 0;//傳入參數合法性檢測  
  28.     needed+=p->offset;//須要額外分配的內存 也就是偏移量  
  29.     if (needed<=p->length) return p->buffer+p->offset;//內存夠用直接返回  
  30.     newsize=pow2gt(needed);  
  31.     newbuffer=(char*)cJSON_malloc(newsize);//malloc出新內存 放buffer裏面的內容  
  32.     if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}  
  33.     if (newbuffer) memcpy(newbuffer,p->buffer,p->length);//  
  34.     cJSON_free(p->buffer);//  
  35.     p->length=newsize;  
  36.     p->buffer=newbuffer;  
  37.     return newbuffer+p->offset;//  
  38. }  
  39.   
  40. char *cJSON_Print(cJSON * item)  
  41. {  
  42.     return print_value(item, 0, 1, 0);  
  43. }  
  44.   
  45. static char *print_value(cJSON * item, int depth, int fmt, printbuffer * p)  
  46. {  
  47.     char *out = 0;  
  48.   
  49.     if (!item)  
  50.         return 0;  
  51.     if (p) {  
  52.         switch ((item->type) & 255) {  
  53.         case cJSON_NULL:{  
  54.                 out = ensure(p, 5);  
  55.                 if (out)  
  56.                     strcpy(out, "null");  
  57.                 break;  
  58.             }  
  59.         case cJSON_False:{  
  60.                 out = ensure(p, 6);  
  61.                 if (out)  
  62.                     strcpy(out, "false");  
  63.                 break;  
  64.             }  
  65.         case cJSON_True:{  
  66.                 out = ensure(p, 5);  
  67.                 if (out)  
  68.                     strcpy(out, "true");  
  69.                 break;  
  70.             }  
  71.         case cJSON_Number:  
  72.             out = print_number(item, p);  //打印數字函數  
  73.             break;  
  74.         case cJSON_String:  
  75.             out = print_string(item, p);  //打印字符串函數  
  76.             break;  
  77.         case cJSON_Array:  
  78.             out = print_array(item, depth, fmt, p);  //打印數組函數  
  79.             break;  
  80.         case cJSON_Object:  
  81.             out = print_object(item, depth, fmt, p);  //打印object對象類型的函數  
  82.             break;  
  83.         }  
  84.     } else {  
  85.         switch ((item->type) & 255) {  
  86.         case cJSON_NULL:  
  87.             out = cJSON_strdup("null");  
  88.             break;  
  89.         case cJSON_False:  
  90.             out = cJSON_strdup("false");  
  91.             break;  
  92.         case cJSON_True:  
  93.             out = cJSON_strdup("true");  
  94.             break;  
  95.         case cJSON_Number:  
  96.             out = print_number(item, 0);  
  97.             break;  
  98.         case cJSON_String:  
  99.             out = print_string(item, 0);  
  100.             break;  
  101.         case cJSON_Array:  
  102.             out = print_array(item, depth, fmt, 0);  
  103.             break;  
  104.         case cJSON_Object:  
  105.             out = print_object(item, depth, fmt, 0);  
  106.             break;  
  107.         }  
  108.     }  
  109.     return out;  
  110. }  
  111.   
  112.   
  113. static char *print_number(cJSON * item, printbuffer * p)  //打印數字函數  
  114. {  
  115.     char *str = 0;  
  116.     double d = item->valuedouble;  
  117.   
  118.     if (d == 0) {  
  119.         if (p)  
  120.             str = ensure(p, 2);  
  121.         else  
  122.             str = (char *) cJSON_malloc(2); /* special case for 0. */  
  123.         if (str)  
  124.             strcpy(str, "0");  
  125.     } else if (fabs(((double) item->valueint) - d) <= DBL_EPSILON  
  126.            && d <= INT_MAX && d >= INT_MIN) {  
  127.         if (p)  
  128.             str = ensure(p, 21);  
  129.         else  
  130.             str = (char *) cJSON_malloc(21);    /* 2 ^ 64 + 1能夠用21個字符表示 */  
  131.         if (str)  
  132.             sprintf(str, "%d", item->valueint);  
  133.     } else {  
  134.         if (p)  
  135.             str = ensure(p, 64);  
  136.         else  
  137.             str = (char *) cJSON_malloc(64);    /* This is a nice tradeoff. */  
  138.         if (str) {  
  139.             if (fpclassify(d) != FP_ZERO && !isnormal(d)) //非正常浮點數  
  140.                 sprintf(str, "null");  
  141.             else if (fabs(floor(d) - d) <= DBL_EPSILON  
  142.                  && fabs(d) < 1.0e60)  
  143.                 sprintf(str, "%.0f", d);  
  144.             else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)  
  145.                 sprintf(str, "%e", d);  
  146.             else  
  147.                 sprintf(str, "%f", d);  
  148.         }  
  149.     }  
  150.     return str;  
  151. }  
  152.   
  153.   
  154. static char *print_string(cJSON * item, printbuffer * p) //打印字符串類型的結點  
  155. {  
  156.     return print_string_ptr(item->valuestring, p);  
  157. }  
  158.   
  159. static char *print_string_ptr(const char *str, printbuffer * p)   //打印字符串類型的結點  
  160. {  
  161.     const char *ptr;  
  162.     char *ptr2, *out;  
  163.     int len = 0, flag = 0;  
  164.     unsigned char token;  
  165.   
  166.     if (!str) {  
  167.         if (p)  
  168.             out = ensure(p, 3);  
  169.         else  
  170.             out = (char *) cJSON_malloc(3);  
  171.         if (!out)  
  172.             return 0;  
  173.         strcpy(out, "\"\"");     //字符串爲空  
  174.         return out;  
  175.     }  
  176.   
  177.     for (ptr = str; *ptr; ptr++)  
  178.         flag |= ((*ptr > 0 && *ptr < 32) || (*ptr == '\"')  
  179.              || (*ptr == '\\')) ? 1 : 0;  
  180.     if (!flag) {            //對字符串中不含'\','/',空格等字符的字符處理  
  181.         len = ptr - str;  
  182.         if (p)  
  183.             out = ensure(p, len + 3);  
  184.         else  
  185.             out = (char *) cJSON_malloc(len + 3);  
  186.         if (!out)  
  187.             return 0;  
  188.         ptr2 = out;  
  189.         *ptr2++ = '\"';  
  190.         strcpy(ptr2, str);  
  191.         ptr2[len] = '\"';  
  192.         ptr2[len + 1] = 0;  
  193.         return out;  
  194.     }  
  195.   
  196.     ptr = str;  
  197.     while ((token = *ptr) && ++len) {  
  198.         if (strchr("\"\\\b\f\n\r\t", token))  
  199.             len++;  
  200.         else if (token < 32)  
  201.             len += 5;  
  202.         ptr++;  
  203.     }  
  204.   
  205.     if (p)  
  206.         out = ensure(p, len + 3);  
  207.     else  
  208.         out = (char *) cJSON_malloc(len + 3);  
  209.     if (!out)  
  210.         return 0;  
  211.   
  212.     ptr2 = out;  
  213.     ptr = str;  
  214.     *ptr2++ = '\"';  
  215.     while (*ptr) {  
  216.         if ((unsigned char) *ptr > 31 && *ptr != '\"'  
  217.             && *ptr != '\\')  
  218.             *ptr2++ = *ptr++;  
  219.         else {  
  220.             *ptr2++ = '\\';  
  221.             switch (token = *ptr++) {  
  222.             case '\\':  
  223.                 *ptr2++ = '\\';  
  224.                 break;  
  225.             case '\"':  
  226.                 *ptr2++ = '\"';  
  227.                 break;  
  228.             case '\b':  
  229.                 *ptr2++ = 'b';  
  230.                 break;  
  231.             case '\f':  
  232.                 *ptr2++ = 'f';  
  233.                 break;  
  234.             case '\n':  
  235.                 *ptr2++ = 'n';  
  236.                 break;  
  237.             case '\r':  
  238.                 *ptr2++ = 'r';  
  239.                 break;  
  240.             case '\t':  
  241.                 *ptr2++ = 't';  
  242.                 break;  
  243.             default:  
  244.                 sprintf(ptr2, "u%04x", token);  
  245.                 ptr2 += 5;  
  246.                 break;  /* escape and print */  
  247.             }  
  248.         }  
  249.     }  
  250.     *ptr2++ = '\"';  
  251.     *ptr2++ = 0;  
  252.     return out;  
  253. }  
  254.   
  255.   
  256. static char *print_array(cJSON * item, int depth, int fmt, printbuffer * p)   //打印數組類型結點函數  
  257. {  
  258.     char **entries;  
  259.     char *out = 0, *ptr, *ret;  
  260.     int len = 5;  
  261.     cJSON *child = item->child;  
  262.     int numentries = 0, i = 0, fail = 0;  
  263.     size_t tmplen = 0;  
  264.   
  265.     /* 數組裏有多少個元素 */  
  266.     while (child)  
  267.         numentries++, child = child->next;  
  268.     /* 明確處理numentries = = 0 */   //處理空數組  
  269.     if (!numentries) {  
  270.         if (p)  
  271.             out = ensure(p, 3);  
  272.         else  
  273.             out = (char *) cJSON_malloc(3);  
  274.         if (out)  
  275.             strcpy(out, "[]");  
  276.         return out;  
  277.     }  
  278.   
  279.     if (p) {  
  280.         /* 組成數組的輸出形式 */  
  281.         i = p->offset;  
  282.         ptr = ensure(p, 1);  
  283.         if (!ptr)  
  284.             return 0;  
  285.         *ptr = '[';  
  286.         p->offset++;  
  287.         child = item->child;  
  288.         while (child && !fail) {  
  289.             print_value(child, depth + 1, fmt, p);  
  290.             p->offset = update(p);  
  291.             if (child->next) {  
  292.                 len = fmt ? 2 : 1;  
  293.                 ptr = ensure(p, len + 1);  
  294.                 if (!ptr)  
  295.                     return 0;  
  296.                 *ptr++ = ',';  
  297.                 if (fmt)  
  298.                     *ptr++ = ' ';  
  299.                 *ptr = 0;  
  300.                 p->offset += len;  
  301.             }  
  302.             child = child->next;  
  303.         }  
  304.         ptr = ensure(p, 2);  
  305.         if (!ptr)  
  306.             return 0;  
  307.         *ptr++ = ']';  
  308.         *ptr = 0;  
  309.         out = (p->buffer) + i;  
  310.     } else {  
  311.         /* 分配一個指針數組存儲數組裏的每個元素的打印結果 */  
  312.         entries =  
  313.             (char **) cJSON_malloc(numentries * sizeof(char *));  
  314.         if (!entries)  
  315.             return 0;  
  316.         memset(entries, 0, numentries * sizeof(char *));  
  317.         /* 檢索全部結果: */  
  318.         child = item->child;  
  319.         while (child && !fail) {  
  320.             ret = print_value(child, depth + 1, fmt, 0);  
  321.             entries[i++] = ret;  
  322.             if (ret)  
  323.                 len += strlen(ret) + 2 + (fmt ? 1 : 0);  
  324.             else  
  325.                 fail = 1;  
  326.             child = child->next;  
  327.         }  
  328.   
  329.           
  330.         if (!fail)  
  331.             out = (char *) cJSON_malloc(len);  
  332.           
  333.         if (!out)  
  334.             fail = 1;  
  335.   
  336.       
  337.         if (fail) {  
  338.             for (i = 0; i < numentries; i++)  
  339.                 if (entries[i])  
  340.                     cJSON_free(entries[i]);  
  341.             cJSON_free(entries);  
  342.             return 0;  
  343.         }  
  344.   
  345.         /* 組成數組的輸出形式. */  
  346.         *out = '[';  
  347.         ptr = out + 1;  
  348.         *ptr = 0;  
  349.         for (i = 0; i < numentries; i++) {  
  350.             tmplen = strlen(entries[i]);  
  351.             memcpy(ptr, entries[i], tmplen);  
  352.             ptr += tmplen;  
  353.             if (i != numentries - 1) {  
  354.                 *ptr++ = ',';  
  355.                 if (fmt)  
  356.                     *ptr++ = ' ';  
  357.                 *ptr = 0;  
  358.             }  
  359.             cJSON_free(entries[i]);  
  360.         }  
  361.         cJSON_free(entries);  
  362.         *ptr++ = ']';  
  363.         *ptr++ = 0;  
  364.     }  
  365.     return out;  
  366. }  
  367.   
  368. /* 打印object類型結點. */  
  369. static char *print_object(cJSON * item, int depth, int fmt,  printbuffer * p)  
  370. {  
  371.     char **entries = 0, **names = 0;  
  372.     char *out = 0, *ptr, *ret, *str;  
  373.     int len = 7, i = 0, j;  
  374.     cJSON *child = item->child;  
  375.     int numentries = 0, fail = 0;  
  376.     size_t tmplen = 0;  
  377.   
  378.     /* 統計有多少個子結點. */  
  379.     while (child)  
  380.         numentries++, child = child->next;  
  381.     /* 明確處理空對象的狀況*/  
  382.     if (!numentries) {  
  383.         if (p)  
  384.             out = ensure(p, fmt ? depth + 4 : 3);  
  385.         else  
  386.             out = (char *) cJSON_malloc(fmt ? depth + 4 : 3);  
  387.         if (!out)  
  388.             return 0;  
  389.         ptr = out;  
  390.         *ptr++ = '{';  
  391.         if (fmt) {  
  392.             *ptr++ = '\n';  
  393.             for (i = 0; i < depth; i++)  
  394.                 *ptr++ = '\t';  
  395.         }  
  396.         *ptr++ = '}';  
  397.         *ptr++ = 0;  
  398.         return out;  
  399.     }  
  400.     if (p) {  
  401.         /* 組成輸出形式: */  
  402.         i = p->offset;  
  403.         len = fmt ? 2 : 1;  
  404.         ptr = ensure(p, len + 1);  
  405.         if (!ptr)  
  406.             return 0;  
  407.         *ptr++ = '{';  
  408.         if (fmt)  
  409.             *ptr++ = '\n';  
  410.         *ptr = 0;  
  411.         p->offset += len;  
  412.         child = item->child;  
  413.         depth++;  
  414.         while (child) {  
  415.             if (fmt) {  
  416.                 ptr = ensure(p, depth);  
  417.                 if (!ptr)  
  418.                     return 0;  
  419.                 for (j = 0; j < depth; j++)  
  420.                     *ptr++ = '\t';  
  421.                 p->offset += depth;  
  422.             }  
  423.             print_string_ptr(child->string, p);  
  424.             p->offset = update(p);  
  425.   
  426.             len = fmt ? 2 : 1;  
  427.             ptr = ensure(p, len);  
  428.             if (!ptr)  
  429.                 return 0;  
  430.             *ptr++ = ':';  
  431.             if (fmt)  
  432.                 *ptr++ = '\t';  
  433.             p->offset += len;  
  434.   
  435.             print_value(child, depth, fmt, p);  
  436.             p->offset = update(p);  
  437.   
  438.             len = (fmt ? 1 : 0) + (child->next ? 1 : 0);  
  439.             ptr = ensure(p, len + 1);  
  440.             if (!ptr)  
  441.                 return 0;  
  442.             if (child->next)  
  443.                 *ptr++ = ',';  
  444.             if (fmt)  
  445.                 *ptr++ = '\n';  
  446.             *ptr = 0;  
  447.             p->offset += len;  
  448.             child = child->next;  
  449.         }  
  450.         ptr = ensure(p, fmt ? (depth + 1) : 2);  
  451.         if (!ptr)  
  452.             return 0;  
  453.         if (fmt)  
  454.             for (i = 0; i < depth - 1; i++)  
  455.                 *ptr++ = '\t';  
  456.         *ptr++ = '}';  
  457.         *ptr = 0;  
  458.         out = (p->buffer) + i;  
  459.     } else {  
  460.         /*爲對象和名稱分配空間 */  
  461.         entries =  
  462.             (char **) cJSON_malloc(numentries * sizeof(char *));  
  463.         if (!entries)  
  464.             return 0;  
  465.         names =  
  466.             (char **) cJSON_malloc(numentries * sizeof(char *));  
  467.         if (!names) {  
  468.             cJSON_free(entries);  
  469.             return 0;  
  470.         }  
  471.         memset(entries, 0, sizeof(char *) * numentries);  
  472.         memset(names, 0, sizeof(char *) * numentries);  
  473.   
  474.         /* 將全部結果收集到數組: */  
  475.         child = item->child;  
  476.         depth++;  
  477.         if (fmt)  
  478.             len += depth;  
  479.         while (child && !fail) {  
  480.             names[i] = str =  
  481.                 print_string_ptr(child->string, 0);  
  482.             entries[i++] = ret =  
  483.                 print_value(child, depth, fmt, 0);  
  484.             if (str && ret)  
  485.                 len +=  
  486.                     strlen(ret) + strlen(str) + 2 +  
  487.                     (fmt ? 2 + depth : 0);  
  488.             else  
  489.                 fail = 1;  
  490.             child = child->next;  
  491.         }  
  492.   
  493.   
  494.         if (!fail)  
  495.             out = (char *) cJSON_malloc(len);  
  496.         if (!out)  
  497.             fail = 1;  
  498.   
  499.       
  500.         if (fail) {  
  501.             for (i = 0; i < numentries; i++) {  
  502.                 if (names[i])  
  503.                     cJSON_free(names[i]);  
  504.                 if (entries[i])  
  505.                     cJSON_free(entries[i]);  
  506.             }  
  507.             cJSON_free(names);  
  508.             cJSON_free(entries);  
  509.             return 0;  
  510.         }  
  511.   
  512.         /* 組成輸出形式: */  
  513.         *out = '{';  
  514.         ptr = out + 1;  
  515.         if (fmt)  
  516.             *ptr++ = '\n';  
  517.         *ptr = 0;  
  518.         for (i = 0; i < numentries; i++) {  
  519.             if (fmt)  
  520.                 for (j = 0; j < depth; j++)  
  521.                     *ptr++ = '\t';  
  522.             tmplen = strlen(names[i]);  
  523.             memcpy(ptr, names[i], tmplen);  
  524.             ptr += tmplen;  
  525.             *ptr++ = ':';  
  526.             if (fmt)  
  527.                 *ptr++ = '\t';  
  528.             strcpy(ptr, entries[i]);  
  529.             ptr += strlen(entries[i]);  
  530.             if (i != numentries - 1)  
  531.                 *ptr++ = ',';  
  532.             if (fmt)  
  533.                 *ptr++ = '\n';  
  534.             *ptr = 0;  
  535.             cJSON_free(names[i]);  
  536.             cJSON_free(entries[i]);  
  537.         }  
  538.   
  539.         cJSON_free(names);  
  540.         cJSON_free(entries);  
  541.         if (fmt)  
  542.             for (i = 0; i < depth - 1; i++)  
  543.                 *ptr++ = '\t';  
  544.         *ptr++ = '}';  
  545.         *ptr++ = 0;  
  546.     }  
  547.     return out;  
  548. }  

cJSON解析:

首先,調用cJSON_Parse()函數,此函數是一個二次封裝函數,其內部爲cJSON_ParseWithOpts()函數,該函數用於提取更多的解析選項,若是須要,最後返回解析結束的位置。而在上面的函數中,調用parse_value()函數進行解析,而該函數首先建立cJSON_NewItem()建立節點,用於存放解析的JSON結構數據,而後根據不一樣的選項,調用解析函數,其爲parse_string(),parse_number(),parse_array(),parse_objec()等。


結構圖以下:


相關函數以下:

  1. // cJSON解析的二次封裝函數  
  2. cJSON *cJSON_Parse(const char *value)  
  3. {  
  4.     return cJSON_ParseWithOpts(value,0,0);  
  5. }     
  6.   
  7. // 解析對象,建立一個新的根並初始化,返回一個cJSON類型  
  8. cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)  
  9. {  
  10.     const char *end=0;  
  11.     cJSON *c=cJSON_New_Item();   //建立一個新結點  
  12.     ep=0; //ep爲全局變量,錯誤信息就保存在全局字符串指針ep裏,調用cJSON_GetErrorPtr()能夠得要錯誤緣由的描述字符串  
  13.     if (!c)  
  14.         return 0;        
  15.   
  16.     end=parse_value(c,skip(value));  
  17.     if (!end)  
  18.     {  
  19.         cJSON_Delete(c);  
  20.         return 0;  
  21.     }   /* parse failure. ep is set. */  
  22.   
  23.     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */  
  24.     if (require_null_terminated)  
  25.     {  
  26.         end=skip(end);  
  27.         if (*end)  
  28.         {  
  29.             cJSON_Delete(c);  
  30.             ep=end;  
  31.             return 0;  
  32.         }  
  33.     }  
  34.     if (return_parse_end)  
  35.         *return_parse_end=end;  
  36.     return c;  
  37. }  
  38.   
  39. // 解析器核心函數  
  40. static const char *parse_value(cJSON *item,const char *value)  
  41. {  
  42.     if (!value)  
  43.         return 0;   /* Fail on null. */  
  44.     if (!strncmp(value,"null",4))  
  45.     {  
  46.         item->type=cJSON_NULL;  
  47.         return value+4;  
  48.     }  
  49.     if (!strncmp(value,"false",5))  
  50.     {  
  51.         item->type=cJSON_False;  
  52.         return value+5;  
  53.     }  
  54.     if (!strncmp(value,"true",4))  
  55.     {  
  56.         item->type=cJSON_True;  
  57.         item->valueint=1;  
  58.         return value+4;  
  59.     }  
  60.     if (*value=='\"')  
  61.     {  
  62.         return parse_string(item,value);  
  63.     }  
  64.     if (*value=='-' || (*value>='0' && *value<='9'))  
  65.     {  
  66.         return parse_number(item,value);  
  67.     }  
  68.     if (*value=='[')  
  69.     {  
  70.         return parse_array(item,value);  
  71.     }  
  72.     if (*value=='{')  
  73.     {  
  74.         return parse_object(item,value);  
  75.     }  
  76.   
  77.     ep=value;  
  78.     return 0;   /* failure. */  
  79. }  
  80.   
  81. static const char *parse_string(cJSON *item,const char *str)   //解析字符串函數  
  82. {  
  83.     const char *ptr=str+1;  
  84.     char *ptr2;  
  85.     char *out;  
  86.     int len=0;  
  87.     unsigned uc,uc2;  
  88.     if (*str!='\"')    // 不是字符串狀況  
  89.     {  
  90.         ep=str;  
  91.         return 0;  
  92.     }   /* not a string! */  
  93.   
  94.     while (*ptr!='\"' && *ptr && ++len)  
  95.         if (*ptr++ == '\\')  
  96.             ptr++;   // 跳出前面的引用  
  97.   
  98.     out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */  
  99.     if (!out)  
  100.         return 0;  
  101.   
  102.     ptr=str+1;  
  103.     ptr2=out;  
  104.     while (*ptr!='\"' && *ptr)  
  105.     {  
  106.         if (*ptr!='\\')  
  107.             *ptr2++=*ptr++;  
  108.         else  
  109.         {  
  110.             ptr++;  
  111.             switch (*ptr)  
  112.             {  
  113.                 case 'b': *ptr2++='\b'; break;  
  114.                 case 'f': *ptr2++='\f'; break;  
  115.                 case 'n': *ptr2++='\n'; break;  
  116.                 case 'r': *ptr2++='\r'; break;  
  117.                 case 't': *ptr2++='\t'; break;  
  118.                 case 'u':    /* transcode utf16 to utf8. */  
  119.                     uc=parse_hex4(ptr+1);  
  120.                         ptr+=4; /* get the unicode char. */  
  121.   
  122.                     if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)  
  123.                         break;  /* check for invalid.   */  
  124.   
  125.                     if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.   */  
  126.                     {  
  127.                         if (ptr[1]!='\\' || ptr[2]!='u')  
  128.                             break;  /* missing second-half of surrogate.    */  
  129.                         uc2=parse_hex4(ptr+3);ptr+=6;  
  130.                         if (uc2<0xDC00 || uc2>0xDFFF)  
  131.                             break;  /* invalid second-half of surrogate.    */  
  132.                         uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));  
  133.                     }  
  134.   
  135.                     len=4;  
  136.                     if (uc<0x80)  
  137.                         len=1;  
  138.                     else if (uc<0x800)  
  139.                         len=2;  
  140.                     else if (uc<0x10000)  
  141.                         len=3;  
  142.                     ptr2+=len;  
  143.   
  144.                     switch (len)  
  145.                     {  
  146.                         case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;  
  147.                         case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;  
  148.                         case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;  
  149.                         case 1: *--ptr2 =(uc | firstByteMark[len]);  
  150.                     }  
  151.                     ptr2+=len;  
  152.                     break;  
  153.                 default:  *ptr2++=*ptr; break;  
  154.             }  
  155.             ptr++;  
  156.         }  
  157.     }  
  158.     *ptr2=0;  
  159.     if (*ptr=='\"') ptr++;  
  160.     item->valuestring=out;  
  161.     item->type=cJSON_String;  
  162.     return ptr;  
  163. }  
  164.   
  165. // 跳過這些空格,這裏跳過了ascii值小於32的。  
  166. static const char *skip(const char *in)  
  167. {  
  168.     while (in && *in && (unsigned char)*in<=32)  
  169.         in++;  
  170.     return in;  
  171. }  
  172.   
  173. // parse_number函數功能:解析數字,對輸入的文本生成一個數字,並填充結果項,傳入參數有兩  
  174. // 個,這裏先只關注num,返回值是一個字符串  
  175. static const char *parse_number(cJSON *item,const char *num)  
  176. {  
  177.     double n=0,sign=1,scale=0;  
  178.     int subscale=0,signsubscale=1;  
  179.   
  180.     if (*num=='-') sign=-1,num++;      // 判斷數字是不是有符號數字  
  181.     if (*num=='0') num++;                  // 判斷數字是否爲0  
  182.     if (*num>='1' && *num<='9')  
  183.         do                               // 轉換數字  
  184.             n=(n*10.0)+(*num++ -'0');  
  185.         while (*num>='0' && *num<='9');  
  186.     if (*num=='.' && num[1]>='0' && num[1]<='9') // 對小數點後邊的部分進行處理,scale記錄小數點後邊的位數  
  187.     {  
  188.         num++;  
  189.         do  
  190.             n=(n*10.0)+(*num++ -'0'),scale--;       // scale爲小數點後的位數  
  191.         while (*num>='0' && *num<='9');  
  192.     }  
  193.     if (*num=='e' || *num=='E')        // 是否爲指數,科學計數法  
  194.     {  
  195.         num++;  
  196.         if (*num=='+')                 // 判斷指數後邊冪的正負號  
  197.             num++;  
  198.         else if (*num=='-')  
  199.             signsubscale=-1,num++;  
  200.         while (*num>='0' && *num<='9') // 處理指數後邊10的冪  
  201.             subscale=(subscale*10)+(*num++ - '0');  
  202.     }  
  203.     // 將字符串轉換爲相應的數值  
  204.     n=sign*n*pow(10.0,(scale+subscale*signsubscale));   /* number = +/- number.fraction * 10^+/- exponent */  
  205.   
  206.     item->valuedouble=n;             // 將算出來的值存入緩存  
  207.     item->valueint=(int)n;           // 將算出來的值存入緩存  
  208.     item->type=cJSON_Number;         // 目標類型爲數字  
  209.     return num;  
  210. }  
  211.   
  212. // 從輸入文本中構建array  
  213. static const char *parse_array(cJSON *item,const char *value)  
  214. {  
  215.     cJSON *child;  
  216.     if (*value!='[')    {ep=value;return 0;}    /* not an array! */  
  217.   
  218.     item->type=cJSON_Array;  
  219.     value=skip(value+1);  
  220.     if (*value==']') return value+1;    /* empty array. */  
  221.   
  222.     item->child=child=cJSON_New_Item();  
  223.     if (!item->child) return 0;      /* memory fail */  
  224.     value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */  
  225.     if (!value) return 0;  
  226.   
  227.     while (*value==',')  
  228.     {  
  229.         cJSON *new_item;  
  230.         if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */  
  231.         child->next=new_item;new_item->prev=child;child=new_item;  
  232.         value=skip(parse_value(child,skip(value+1)));  
  233.         if (!value) return 0;   /* memory fail */  
  234.     }  
  235.   
  236.     if (*value==']') return value+1;    /* end of array */  
  237.     ep=value;return 0;  /* malformed. */  
  238. }  
  239. // 從輸入文本中構建object  
  240. static const char *parse_object(cJSON *item,const char *value)  
  241. {  
  242.     cJSON *child;  
  243.     if (*value!='{')    {ep=value;return 0;}    /* not an object! */  
  244.   
  245.     item->type=cJSON_Object;  
  246.     value=skip(value+1);  
  247.     if (*value=='}') return value+1;    /* empty array. */  
  248.   
  249.     item->child=child=cJSON_New_Item();  
  250.     if (!item->child) return 0;  
  251.     value=skip(parse_string(child,skip(value)));  
  252.     if (!value) return 0;  
  253.     child->string=child->valuestring;child->valuestring=0;  
  254.     if (*value!=':') {ep=value;return 0;}   /* fail! */  
  255.     value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */  
  256.     if (!value) return 0;  
  257.   
  258.     while (*value==',')  
  259.     {  
  260.         cJSON *new_item;  
  261.         if (!(new_item=cJSON_New_Item()))   return 0; /* memory fail */  
  262.         child->next=new_item;new_item->prev=child;child=new_item;  
  263.         value=skip(parse_string(child,skip(value+1)));  
  264.         if (!value) return 0;  
  265.         child->string=child->valuestring;child->valuestring=0;  
  266.         if (*value!=':') {ep=value;return 0;}   /* fail! */  
  267.         value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */  
  268.         if (!value) return 0;  
  269.     }  
  270.   
  271.     if (*value=='}') return value+1;    /* end of array */  
  272.     ep=value;return 0;  /* malformed. */  
  273. }  
  274.   
  275. // 將十六進制的字符串轉換爲數字表示!  
  276. static unsigned parse_hex4(const char *str)  
  277. {  
  278.     unsigned h=0;  
  279.     if (*str>='0' && *str<='9')  
  280.         h+=(*str)-'0';  
  281.     else if (*str>='A' && *str<='F')  
  282.         h+=10+(*str)-'A';  
  283.     else if (*str>='a' && *str<='f')  
  284.         h+=10+(*str)-'a';  
  285.     else  
  286.         return 0;  
  287.     h=h<<4;str++;  
  288.     if (*str>='0' && *str<='9')  
  289.         h+=(*str)-'0';  
  290.     else if (*str>='A' && *str<='F')  
  291.         h+=10+(*str)-'A';  
  292.     else if (*str>='a' && *str<='f')  
  293.         h+=10+(*str)-'a';  
  294.     else  
  295.         return 0;  
  296.     h=h<<4;str++;  
  297.     if (*str>='0' && *str<='9')  
  298.         h+=(*str)-'0';  
  299.     else if (*str>='A' && *str<='F')  
  300.         h+=10+(*str)-'A';  
  301.     else if (*str>='a' && *str<='f')  
  302.         h+=10+(*str)-'a';  
  303.     else  
  304.         return 0;  
  305.     h=h<<4;str++;  
  306.     if (*str>='0' && *str<='9')  
  307.         h+=(*str)-'0';  
  308.     else if (*str>='A' && *str<='F')  
  309.         h+=10+(*str)-'A';  
  310.     else if (*str>='a' && *str<='f')  
  311.         h+=10+(*str)-'a';  
  312.     else  
  313.         return 0;  
  314.     return h;  
  315. }  

cJSON內存管理:

hook管理函數:

在 c 語言中內存通常是 malloc 和 free 的。
爲了方便用戶自由的管理內存, cjson 使用 Hook 技術來讓使用者能夠自定義內存管理函數。
即用戶自定義 malloc 和 free.
具體實現方式能夠參考下面的代碼, 默認使用系統的 malloc 和 free 函數, 用過 cJSON_InitHooks 函數能夠替換成用戶自定義的 malloc 和 free 函數。

  1. typedef struct cJSON_Hooks  
  2. {  
  3.   void *(*malloc_fn)(size_t sz);  
  4.   void (*free_fn)(void *ptr);  
  5. } cJSON_Hooks;  
  6.   
  7. // 對cJSON提供的分配,再分配,釋放內存初始化函數  
  8. extern void cJSON_InitHooks(cJSON_Hooks* hooks);  
  9.   
  10. // 默認將分配和釋放空間函數指針指向malloc和free  
  11. static void *(*cJSON_malloc)(size_t sz) = malloc;  
  12. static void (*cJSON_free)(void *ptr) = free;  
  13. // 其使用Hook技術來讓使用者能夠自定義內存管理函數。其中默認系統使用的內存分配和釋放函數是malloc  
  14. // 和free函數,利用cJSON_InitHooks函數能夠替換成用戶自定義的malloc和free函數。  
  15. void cJSON_InitHooks(cJSON_Hooks* hooks)  
  16. {  
  17.         // 若是未定義,則使用默認的malloc和free函數  
  18.     if (!hooks) { /* Reset hooks */  
  19.         cJSON_malloc = malloc;  
  20.         cJSON_free = free;  
  21.         return;  
  22.     }  
  23.     // 定義了,則使用用戶自定義的malloc和free函數  
  24.     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;  
  25.     cJSON_free   = (hooks->free_fn)?hooks->free_fn:free;  
  26. }  

cJSON的刪除:

刪除節點很簡單, 先刪除兒子,而後清理內存便可。
總結一下就是對於 object 和 array 須要先刪除兒子,而後刪除本身。
對於 字符串, 須要先釋放字符串的內存, 再釋放本身這塊內存。
對於其餘節點,直接釋放本身這塊內存。

  1. /*刪除結點函數*/  
  2. void cJSON_Delete(cJSON *c) {  
  3.     cJSON *next;  
  4.     while (c) {  
  5.         next=c->next;  
  6.         if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);  
  7.         if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);  
  8.         if (c->string) cJSON_free(c->string);  
  9.         cJSON_free(c);  
  10.         c=next;  
  11.     }  
  12. }  
  13.   
  14.   
  15. /*刪除兒子結點函數*/  
  16. 刪除也是從 array 和 object 中刪除,實現就比較簡潔了。  
  17. void   cJSON_DeleteItemFromArray(cJSON *array,int which) {  
  18.     cJSON_Delete(cJSON_DetachItemFromArray(array,which));  
  19. }  
  20. void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {  
  21.     cJSON_Delete(cJSON_DetachItemFromObject(object,string));  
  22. }  


Detach 又是什麼東西呢?
咱們把一個節點從 json 樹中刪除, 可是不釋放內存,而是先保留這個節點的指針, 這樣儲存在這個節點的信息都保留了下來。
接下來咱們就能夠作不少事了, 合適的時候添加到其餘對象中, 合適的時候釋放內存。
好比上面的 delete 函數, 就須要真實的刪除了, 這個時候咱們刪除便可。
而 detach 實現也比較簡單, 只是少了一步刪除操做。

  1. // 節點從雙向鏈表中刪除便可  
  2. cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {  
  3.     cJSON *c=array->child;  
  4.     while (c && which>0) c=c->next,which--;  
  5.     if (!c) return 0;  
  6.     if (c->prev) c->prev->next=c->next;  
  7.     if (c->next) c->next->prev=c->prev;  
  8.     if (c==array->child) array->child=c->next;  
  9.     c->prev=c->next=0;  
  10.     return c;  
  11. }  
  12. cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {  
  13.     int i=0;  
  14.     cJSON *c=object->child;  
  15.     while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;  
  16.     if (c) return cJSON_DetachItemFromArray(object,i);  
  17.     return 0;  
  18. }  


其餘函數:

前面咱們已經將json功能分爲三大塊進行了解析,如今把剩餘的一些函數貼上,這些函數單獨分析便可。

    1. // 返回節點的個數  
    2. int cJSON_GetArraySize(cJSON *array)  
    3. {  
    4.     cJSON *c=array->child;  
    5.     int i=0;  
    6.     while(c)  
    7.         i++,c=c->next;  
    8.     return i;  
    9. }  
    10.   
    11. // 返回array中第item個節點的地址  
    12. cJSON *cJSON_GetArrayItem(cJSON *array,int item)  
    13. {  
    14.     cJSON *c=array->child;  
    15.     while (c && item>0)  
    16.         item--,c=c->next;  
    17.     return c;  
    18. }  
    19.   
    20.   
    21. // 返回Object中第item個節點的地址  
    22. cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)  
    23. {  
    24.     cJSON *c=object->child;  
    25.     while (c && cJSON_strcasecmp(c->string,string))  
    26.         c=c->next;  
    27.     return c;  
    28. }  
    29.   
    30. //在鏈表中插入一個新結點  
    31. void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem)  
    32. {  
    33.     cJSON *c=array->child;  
    34.     // 找到which位置  
    35.     while (c && which>0)  
    36.      c=c->next,which--;  
    37.     // 添加新的節點到array中  
    38.     if (!c)  
    39.     {  
    40.         cJSON_AddItemToArray(array,newitem);  
    41.         return;  
    42.     }  
    43.     // 將鏈表節點進行掛接  
    44.     newitem->next=c;  
    45.     newitem->prev=c->prev;  
    46.     c->prev=newitem;  
    47.     // 處理arrya的孩子節點  
    48.     if (c==array->child)  
    49.         array->child=newitem;  
    50.     else  
    51.         newitem->prev->next=newitem;  
    52. }  
    53.   
    54.   
    55. // 替換節點操做,用新的節點替換原有的某一個節點  
    56. void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)  
    57. {  
    58.     cJSON *c=array->child;  
    59.     // 找到which位置  
    60.     while (c && which>0)  
    61.         c=c->next,which--;  
    62.     if (!c)  
    63.         return;  
    64.     // 進行掛接  
    65.     newitem->next=c->next;  
    66.     newitem->prev=c->prev;  
    67.     // 處理NULL狀況  
    68.     if (newitem->next)  
    69.         newitem->next->prev=newitem;  
    70.     // 處理孩子節點  
    71.     if (c==array->child)  
    72.         array->child=newitem;  
    73.     else  
    74.         newitem->prev->next=newitem;  
    75.     c->next=c->prev=0;  
    76.     // 刪除替換的節點  
    77.     cJSON_Delete(c);  
    78. }  
    79.   
    80.   
    81. // 替換節點操做  
    82. // 用原有節點替換現有節點  
    83. void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem)  
    84. {  
    85.     int i=0;  
    86.     cJSON *c=object->child;  
    87.     while(c && cJSON_strcasecmp(c->string,string))  
    88.         i++,c=c->next;  
    89.     if(c)  
    90.     {  
    91.         newitem->string=cJSON_strdup(string);  
    92.         cJSON_ReplaceItemInArray(object,i,newitem);  
    93.     }  
    94. }  
    95.   
    96.   
    97. // 拷貝副本操做  
    98. cJSON *cJSON_Duplicate(cJSON *item,int recurse)  
    99. {  
    100.     cJSON *newitem,*cptr,*nptr=0,*newchild;  
    101.     /* Bail on bad ptr */  
    102.     if (!item)  
    103.         return 0;  
    104.     /* Create new item */  
    105.     newitem=cJSON_New_Item();  
    106.     if (!newitem)  
    107.         return 0;  
    108.     /* Copy over all vars */  
    109.     newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;  
    110.     if (item->valuestring)  
    111.     {  
    112.         newitem->valuestring=cJSON_strdup(item->valuestring);  
    113.         if (!newitem->valuestring)  
    114.         {  
    115.             cJSON_Delete(newitem);  
    116.             return 0;  
    117.         }  
    118.     }  
    119.     if (item->string)  
    120.     {  
    121.         newitem->string=cJSON_strdup(item->string);  
    122.         if (!newitem->string)  
    123.         {  
    124.             cJSON_Delete(newitem);  
    125.             return 0;  
    126.         }  
    127.     }  
    128.     /* If non-recursive, then we're done! */  
    129.     if (!recurse)  
    130.         return newitem;  
    131.     /* Walk the ->next chain for the child. */  
    132.     cptr=item->child;  
    133.     while (cptr)  
    134.     {  
    135.         newchild=cJSON_Duplicate(cptr,1);       /* Duplicate (with recurse) each item in the ->next chain */  
    136.         if (!newchild)  
    137.         {  
    138.             cJSON_Delete(newitem);  
    139.             return 0;  
    140.         }  
    141.         if (nptr)  
    142.         {  
    143.             nptr->next=newchild,newchild->prev=nptr;  
    144.             nptr=newchild;  
    145.         }   /* If newitem->child already set, then crosswire ->prev and ->next and move on */  
    146.         else  
    147.         {  
    148.             newitem->child=newchild;  
    149.             nptr=newchild;  
    150.         }                   /* Set newitem->child and move to it */  
    151.         cptr=cptr->next;  
    152.     }  
    153.     return newitem;  
    154. }

原文出處

相關文章
相關標籤/搜索