zoukankan      html  css  js  c++  java
  • cjson源代码解读(三) 解析字符串、数字、数组、对象

    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')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
    	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(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++='';	break;                                     //特殊情况, 则断掉就行
    				case 'f': *ptr2++='f';	break;
    				case 'n': *ptr2++='
    ';	break;
    				case 'r': *ptr2++='
    ';	break;
    				case 't': *ptr2++='	';	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没有什么大的区别。

    主要就是这四个。

  • 相关阅读:
    作男人 一定要有品位
    如何管理“人”
    Facebook怎样开发软件:工程师驱动的文化(转)
    为人处事100条——修身养性,经典收藏!
    抽空看看这些电影
    曹重英:技术人员也要打造人脉竞争力(转)
    动态分段统计SQL
    不成熟男人与成熟男人的区别
    Ubuntu11.10国内更新源地址汇总以及添加方法(目前最全最快的源)
    ubuntu11.10 64bits机器安装flash方法
  • 原文地址:https://www.cnblogs.com/lavi/p/4389358.html
Copyright © 2011-2022 走看看