cjson原始碼解讀(三) 解析字串、數字、數組、對象

來源:互聯網
上載者:User

標籤:

1.  解析數字

static const char *parse_number(cJSON *item,const char *num){double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;if (*num==‘-‘) sign=-1,num++;/* Has sign? */if (*num==‘0‘) num++;/* is zero */if (*num>=‘1‘ && *num<=‘9‘)don=(n*10.0)+(*num++ -‘0‘);while (*num>=‘0‘ && *num<=‘9‘);/* Number? */if (*num==‘.‘ && num[1]>=‘0‘ && num[1]<=‘9‘) {num++;don=(n*10.0)+(*num++ -‘0‘),scale--; while (*num>=‘0‘ && *num<=‘9‘);}/* Fractional part? */if (*num==‘e‘ || *num==‘E‘)/* Exponent? */{num++;if (*num==‘+‘) num++;else if (*num==‘-‘) signsubscale=-1,num++;/* With sign? */while (*num>=‘0‘ && *num<=‘9‘) subscale=(subscale*10)+(*num++ - ‘0‘);/* Number? */}n=sign*n*pow(10.0,(scale+subscale*signsubscale));/* number = +/- number.fraction * 10^+/- exponent */item->valuedouble=n;item->valueint=(int)n;item->type=cJSON_Number;return num;}

 item是傳進來的cjson object, num是起始數字。

  1. 解析正負, 用sign 標記, -1 是負

  2. 判斷是不是0

  3. 判斷小數點前面的數字, 也就是 - 3.2 e 5  , 前面的3.2, 這個分為兩部分, 小數點前和後

  4. e或者E,即科學計數的後半部分, 這個時候需要處理一下科學計數的部分是不是正或者負的問題, 用signsubscale 記錄。

  5. 然後直接解析, 這裡作者用了個小技巧, 作者直接在解析前面基數的部分, 解析出的是整數, 用scale記錄, 最後用科學技術弄回來就OK了, 很巧妙。

  6. 然後返回數字, 解析出來一個Object。

2. 解析字串

static const char *parse_string(cJSON *item,const char *str){const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;if (*str!=‘\"‘) {ep=str;return 0;}/* not a string! */while (*ptr!=‘\"‘ && *ptr && ++len) if (*ptr++ == ‘\\‘) ptr++;/* Skip escaped quotes. */ //跳到字串最後一個去out=(char*)cJSON_malloc(len+1);/* This is how long we need for the string, roughly. */    //預申請一個字串空間大小的空間if (!out) return 0;                                                                        //申請不成功則退出  ptr=str+1;ptr2=out;                                                                        //重新開始, ptr2設定成out開始的部位while (*ptr!=‘\"‘ && *ptr){if (*ptr!=‘\\‘) *ptr2++=*ptr++;                                                    //正常情況下,直接跑下去就行else{ptr++;switch (*ptr){case ‘b‘: *ptr2++=‘\b‘;break;                                     //特殊情況, 則斷掉就行case ‘f‘: *ptr2++=‘\f‘;break;case ‘n‘: *ptr2++=‘\n‘;break;case ‘r‘: *ptr2++=‘\r‘;break;case ‘t‘: *ptr2++=‘\t‘;break;case ‘u‘: /* transcode utf16 to utf8. */                   //unicode 則要單獨處理uc=parse_hex4(ptr+1);ptr+=4;/* get the unicode char. */  //parse hex 在後面, 就是把後四位都弄出來,if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)break;/* check for invalid.*/if (uc>=0xD800 && uc<=0xDBFF)/* UTF16 surrogate pairs.*/{if (ptr[1]!=‘\\‘ || ptr[2]!=‘u‘)break;/* missing second-half of surrogate.*/uc2=parse_hex4(ptr+3);ptr+=6;if (uc2<0xDC00 || uc2>0xDFFF)break;/* invalid second-half of surrogate.*/uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));}len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;switch (len) {case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 1: *--ptr2 =(uc | firstByteMark[len]);}ptr2+=len;break;default:  *ptr2++=*ptr; break;}ptr++;}}*ptr2=0;if (*ptr==‘\"‘) ptr++;item->valuestring=out;item->type=cJSON_String;return ptr;}

 

static unsigned parse_hex4(const char *str){unsigned h=0;if (*str>=‘0‘ && *str<=‘9‘) h+=(*str)-‘0‘; else if (*str>=‘A‘ && *str<=‘F‘) h+=10+(*str)-‘A‘; else if (*str>=‘a‘ && *str<=‘f‘) h+=10+(*str)-‘a‘; else return 0;h=h<<4;str++;if (*str>=‘0‘ && *str<=‘9‘) h+=(*str)-‘0‘; else if (*str>=‘A‘ && *str<=‘F‘) h+=10+(*str)-‘A‘; else if (*str>=‘a‘ && *str<=‘f‘) h+=10+(*str)-‘a‘; else return 0;h=h<<4;str++;if (*str>=‘0‘ && *str<=‘9‘) h+=(*str)-‘0‘; else if (*str>=‘A‘ && *str<=‘F‘) h+=10+(*str)-‘A‘; else if (*str>=‘a‘ && *str<=‘f‘) h+=10+(*str)-‘a‘; else return 0;h=h<<4;str++;if (*str>=‘0‘ && *str<=‘9‘) h+=(*str)-‘0‘; else if (*str>=‘A‘ && *str<=‘F‘) h+=10+(*str)-‘A‘; else if (*str>=‘a‘ && *str<=‘f‘) h+=10+(*str)-‘a‘; else return 0;return h;}

 除了轉碼,剩下的都比較簡單,就是申一個字串, 然後拷過去。

3. 解析數組

static const char *parse_array(cJSON *item,const char *value){cJSON *child;if (*value!=‘[‘){ep=value;return 0;}/* not an array! */item->type=cJSON_Array;value=skip(value+1);if (*value==‘]‘) return value+1;/* empty array. */item->child=child=cJSON_New_Item();if (!item->child) return 0; /* memory fail */value=skip(parse_value(child,skip(value)));/* skip any spacing, get the value. */if (!value) return 0;while (*value==‘,‘){cJSON *new_item;if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */child->next=new_item;new_item->prev=child;child=new_item;value=skip(parse_value(child,skip(value+1)));if (!value) return 0;/* memory fail */}if (*value==‘]‘) return value+1;/* end of array */ep=value;return 0;/* malformed. */}

   如果內容不是空, 然後一直往下解析。 就OK了。 

4. 解析對象,對象以{}表明

static const char *parse_object(cJSON *item,const char *value){cJSON *child;if (*value!=‘{‘){ep=value;return 0;}/* not an object! */item->type=cJSON_Object;value=skip(value+1);if (*value==‘}‘) return value+1;/* empty array. */item->child=child=cJSON_New_Item();if (!item->child) return 0;value=skip(parse_string(child,skip(value)));if (!value) return 0;child->string=child->valuestring;child->valuestring=0;if (*value!=‘:‘) {ep=value;return 0;}/* fail! */value=skip(parse_value(child,skip(value+1)));/* skip any spacing, get the value. */if (!value) return 0;while (*value==‘,‘){cJSON *new_item;if (!(new_item=cJSON_New_Item()))return 0; /* memory fail */child->next=new_item;new_item->prev=child;child=new_item;value=skip(parse_string(child,skip(value+1)));if (!value) return 0;child->string=child->valuestring;child->valuestring=0;if (*value!=‘:‘) {ep=value;return 0;}/* fail! */value=skip(parse_value(child,skip(value+1)));/* skip any spacing, get the value. */if (!value) return 0;}if (*value==‘}‘) return value+1;/* end of array */ep=value;return 0;/* malformed. */}

 就是一個value,一個value往下滾, 然後自己的值用child記錄, 前一個的位置也記錄下來。 跟array沒有什麼大的區別。

 

主要就是這四個。

cjson原始碼解讀(三) 解析字串、數字、數組、對象

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.