⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xtag.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
{    XAttribute *attr;    char *name, *value;    char *s;    if( !parser->valid ) return NULL;    xtag_skip_whitespace( parser );     name = xtag_slurp_to( parser, X_WHITESPACE|X_EQUAL, X_SLASH|X_CLOSETAG );    if( name == NULL ) return NULL;    xtag_skip_whitespace( parser );    s = parser->start;    if( !xtag_assert_and_pass( parser, X_EQUAL ) )    {#ifdef XTAG_DEBUG        printf( "xtag: attr failed EQUAL on <%s>\n", name );#endif        goto err_free_name;    }    xtag_skip_whitespace( parser );    value = xtag_slurp_quoted( parser );    if( value == NULL )    {#ifdef XTAG_DEBUG        printf ("Got NULL quoted attribute value\n");#endif        goto err_free_name;    }    attr = malloc( sizeof (*attr) );    attr->name = name;    attr->value = value;    return attr; err_free_name:    free (name);    parser->valid = VLC_FALSE;    return NULL;}static XTag *xtag_parse_tag( XTagParser *parser ){    XTag *tag, *inner;    XAttribute *attr;    char *name;    char *pcdata;    char *s;    if( !parser->valid ) return NULL;#if 0 /* Do we really want all the whitespace pcdata ? */    xtag_skip_whitespace( parser );#endif    if( (pcdata = xtag_slurp_to( parser, X_OPENTAG, X_NONE )) != NULL )    {        tag = malloc( sizeof(*tag) );        tag->name = NULL;        tag->pcdata = pcdata;        tag->parent = parser->current_tag;        tag->attributes = NULL;        tag->children = NULL;        tag->current_child = NULL;        return tag;    }    s = parser->start;    /* if this starts a close tag, return NULL and let the parent take it */    if( xtag_cin( s[0], X_OPENTAG ) && xtag_cin( s[1], X_SLASH ) )        return NULL;    /* if this starts a comment tag, skip until end */    if( xtag_cin( s[0], X_OPENTAG ) && xtag_cin( s[1], X_QMARK ) &&        xtag_cin( s[2], X_DASH ) && xtag_cin( s[3], X_DASH ) )    {        int xi;        parser->start = s = &s[4];        while( (xi = xtag_index( parser, X_DASH )) >= 0 )        {            parser->start = s = &s[xi+1];            if( xtag_cin( s[0], X_DASH ) && xtag_cin( s[1], X_CLOSETAG ) )            {                parser->start = &s[2];                xtag_skip_whitespace( parser );                return xtag_parse_tag( parser );            }        }        return NULL;    }    /* FIXME: if this starts a DOCTYPE tag, skip until end */    if( xtag_cin( s[0], X_OPENTAG ) && xtag_cin( s[1], X_QMARK ) )    {        int xi = xtag_index( parser, X_CLOSETAG );        if( xi <= 0 ) return NULL;        parser->start = &s[xi+1];        xtag_skip_whitespace( parser );        return xtag_parse_tag( parser );    }    if( !xtag_assert_and_pass( parser, X_OPENTAG ) ) return NULL;    name = xtag_slurp_to( parser, X_WHITESPACE|X_SLASH|X_CLOSETAG, X_NONE );    if( name == NULL ) return NULL;#ifdef XTAG_DEBUG    printf ("<%s ...\n", name);#endif    tag = malloc( sizeof(*tag) );    tag->name = name;    tag->pcdata = NULL;    tag->parent = parser->current_tag;    tag->attributes = NULL;    tag->children = NULL;    tag->current_child = NULL;    s = parser->start;    if( xtag_cin( s[0], X_WHITESPACE ) )    {        while( (attr = xtag_parse_attribute( parser )) != NULL )        {            tag->attributes = xlist_append( tag->attributes, attr );        }    }    xtag_skip_whitespace( parser );    s = parser->start;    if( xtag_cin( s[0], X_CLOSETAG ) )    {        parser->current_tag = tag;        xtag_assert_and_pass( parser, X_CLOSETAG );        while( (inner = xtag_parse_tag( parser ) ) != NULL )        {            tag->children = xlist_append( tag->children, inner );        }        parser->current_tag = tag->parent;        xtag_skip_whitespace( parser );        xtag_assert_and_pass( parser, X_OPENTAG );        xtag_assert_and_pass( parser, X_SLASH );        name = xtag_slurp_to( parser, X_WHITESPACE | X_CLOSETAG, X_NONE );        if( name )        {            if( strcmp( name, tag->name ) )            {#ifdef XTAG_DEBUG                printf ("got %s expected %s\n", name, tag->name);#endif                parser->valid = VLC_FALSE;            }            free( name );        }        xtag_skip_whitespace( parser );        xtag_assert_and_pass( parser, X_CLOSETAG );    }    else    {        xtag_assert_and_pass( parser, X_SLASH );        xtag_assert_and_pass( parser, X_CLOSETAG );    }    return tag;}static XTag *xtag_free( XTag *xtag ){    XList *l;    XAttribute *attr;    XTag *child;    if( xtag == NULL ) return NULL;    if( xtag->name ) free( xtag->name );    if( xtag->pcdata ) free( xtag->pcdata );    for( l = xtag->attributes; l; l = l->next )    {        if( (attr = (XAttribute *)l->data) != NULL )        {            if( attr->name ) free( attr->name );            if( attr->value ) free( attr->value );            free( attr );        }    }    xlist_free( xtag->attributes );    for( l = xtag->children; l; l = l->next )    {        child = (XTag *)l->data;        xtag_free( child );    }    xlist_free( xtag->children );    free( xtag );    return NULL;}static XTag *xtag_new_parse( const char *s, int n ){    XTagParser parser;    XTag *tag, *ttag, *wrapper;    parser.valid = VLC_TRUE;    parser.current_tag = NULL;    parser.start = (char *)s;    if( n == -1 ) parser.end = NULL;    else if( n == 0 )    {#ifdef XTAG_DEBUG        printf ("empty buffer");#endif                return NULL;    }    else parser.end = (char *)&s[n];    /* can't have whitespace pcdata outside rootnode */    xtag_skip_whitespace( &parser );    tag = xtag_parse_tag( &parser );    if( !parser.valid )    {#ifdef XTAG_DEBUG        printf ("invalid file");#endif        xtag_free( tag );        return NULL;    }    if( (ttag = xtag_parse_tag( &parser )) != NULL )    {        if( !parser.valid )        {            xtag_free( ttag );            return tag;        }        wrapper = malloc( sizeof(XTag) );        wrapper->name = NULL;        wrapper->pcdata = NULL;        wrapper->parent = NULL;        wrapper->attributes = NULL;        wrapper->children = NULL;        wrapper->current_child = NULL;        wrapper->children = xlist_append( wrapper->children, tag );        wrapper->children = xlist_append( wrapper->children, ttag );        while( (ttag = xtag_parse_tag( &parser )) != NULL )        {            if( !parser.valid )            {                xtag_free( ttag );                return wrapper;            }            wrapper->children = xlist_append( wrapper->children, ttag );        }        return wrapper;    }    return tag;}static char *xtag_get_name( XTag *xtag ){    return xtag ? xtag->name : NULL;}static char *xtag_get_pcdata( XTag *xtag ){    XList *l;    XTag *child;    if( xtag == NULL ) return NULL;    for( l = xtag->children; l; l = l->next )    {        child = (XTag *)l->data;        if( child->pcdata != NULL )        {            return child->pcdata;        }    }    return NULL;}static char *xtag_get_attribute( XTag *xtag, char *attribute ){    XList *l;    XAttribute *attr;    if( xtag == NULL ) return NULL;    for( l = xtag->attributes; l; l = l->next )    {        if( (attr = (XAttribute *)l->data) != NULL )        {            if( !strcmp( attr->name, attribute ) ) return attr->value;        }    }    return NULL;}static XTag *xtag_first_child( XTag *xtag, char *name ){    XList *l;    XTag *child;    if( xtag == NULL ) return NULL;    if( (l = xtag->children) == NULL ) return NULL;    if( name == NULL )    {        xtag->current_child = l;        return (XTag *)l->data;    }    for( ; l; l = l->next )    {        child = (XTag *)l->data;        if( !strcmp( child->name, name ) )        {            xtag->current_child = l;            return child;        }    }    xtag->current_child = NULL;    return NULL;}static XTag *xtag_next_child( XTag *xtag, char *name ){    XList *l;    XTag *child;    if( xtag == NULL ) return NULL;    if( (l = xtag->current_child) == NULL )        return xtag_first_child( xtag, name );    if( (l = l->next) == NULL ) return NULL;    if( name == NULL )    {        xtag->current_child = l;        return (XTag *)l->data;    }    for( ; l; l = l->next )    {        child = (XTag *)l->data;        if( !strcmp( child->name, name ) )        {            xtag->current_child = l;            return child;        }    }    xtag->current_child = NULL;    return NULL;}/* * This snprints function takes a variable list of char *, the last of * which must be NULL, and prints each in turn to buf. * Returns C99-style total length that would have been written, even if * this is larger than n. */static int xtag_snprints( char *buf, int n, ... ){    va_list ap;    char *s;    int len, to_copy, total = 0;    va_start( ap, n );      for( s = va_arg( ap, char * ); s; s = va_arg( ap, char *) )    {        len = strlen (s);        if( (to_copy = __MIN(n, len) ) > 0 )        {            memcpy( buf, s, to_copy );            buf += to_copy;            n -= to_copy;        }        total += len;    }    va_end( ap );    return total;}static int xtag_snprint( char *buf, int n, XTag *xtag ){    int nn, written = 0;    XList *l;    XAttribute *attr;    XTag *child;#define FORWARD(N) \    buf += __MIN(n, N); \    n = __MAX(n-N, 0);  \    written += N;    if( xtag == NULL )    {        if( n > 0 ) buf[0] = '\0';        return 0;    }    if( xtag->pcdata )    {        nn = xtag_snprints( buf, n, xtag->pcdata, NULL );        FORWARD( nn );        return written;    }    if( xtag->name )    {        nn = xtag_snprints( buf, n, "<", xtag->name, NULL );        FORWARD( nn );        for( l = xtag->attributes; l; l = l->next )        {            attr = (XAttribute *)l->data;                  nn = xtag_snprints( buf, n, " ", attr->name, "=\"", attr->value,                                "\"", NULL);            FORWARD( nn );        }        if( xtag->children == NULL )        {            nn = xtag_snprints ( buf, n, "/>", NULL );            FORWARD( nn );            return written;        }        nn = xtag_snprints( buf, n, ">", NULL );        FORWARD( nn );    }    for( l = xtag->children; l; l = l->next )    {        child = (XTag *)l->data;        nn = xtag_snprint( buf, n, child );        FORWARD( nn );    }    if( xtag->name )    {        nn = xtag_snprints( buf, n, "</", xtag->name, ">", NULL );        FORWARD( nn );    }    return written;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -