📄 xtag.c
字号:
{ 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 + -