cJSONコード読解(5)——JSON文字列の解析

3237 ワード

parse_stringは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; }