cJSONコード読解(5)——JSON文字列の解析
parse_stringはjson文字列解析を行う関数です.
1、まず処理するjsonデータが文字列かどうかを判断する
2、計算文字列の長さ
3、メモリの割り当て
4、jsonの中の文字列の中のすべての文字を遍歴して、普通の文字であれば、直接保存して、もしエスケープ文字であれば特殊な処理を行う必要がある(具体的にはコードを参照)
5、次のjsonデータの位置を返す
1、まず処理するjsonデータが文字列かどうかを判断する
2、計算文字列の長さ
3、メモリの割り当て
4、jsonの中の文字列の中のすべての文字を遍歴して、普通の文字であれば、直接保存して、もしエスケープ文字であれば特殊な処理を行う必要がある(具体的にはコードを参照)
5、次のjsonデータの位置を返す
//
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 json
ptr=str+1;
// ptr2
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++='
'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
// utf16 utf8
case 'u': /* transcode utf16 to utf8. */
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
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++;
}
}
// 0
*ptr2=0;
//
if (*ptr=='\"') ptr++;
//
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}