aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xmltree.c
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-10-02 19:45:26 -0700
committerWilmer van der Gaast <wilmer@gaast.net>2010-10-02 19:45:26 -0700
commit8e9e2b7d9e54744cee32b3724391bf0ad04e8aff (patch)
tree6cafdc57bb8143306daf8ef8288d09754f39b451 /lib/xmltree.c
parent88de0c96136313e553113f69cfc6ae544a5f5954 (diff)
parent2af3e232ff468b288dd4e0dbdab1a17312d801c5 (diff)
Merging mainline, which includes a huge msnp13 merge.
Not 100% sure about the OpenSSL merge, should double check that but I'm currently offline.
Diffstat (limited to 'lib/xmltree.c')
-rw-r--r--lib/xmltree.c106
1 files changed, 94 insertions, 12 deletions
diff --git a/lib/xmltree.c b/lib/xmltree.c
index b0a945ce..bee9007f 100644
--- a/lib/xmltree.c
+++ b/lib/xmltree.c
@@ -140,7 +140,7 @@ void xt_reset( struct xt_parser *xt )
/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on
end-of-stream and 1 otherwise. */
-int xt_feed( struct xt_parser *xt, char *text, int text_len )
+int xt_feed( struct xt_parser *xt, const char *text, int text_len )
{
if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) )
{
@@ -173,20 +173,20 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth )
if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) )
{
- for( i = 0; xt->handlers[i].func; i ++ )
+ if( xt->handlers ) for( i = 0; xt->handlers[i].func; i ++ )
{
/* This one is fun! \o/ */
- /* If handler.name == NULL it means it should always match. */
+ /* If handler.name == NULL it means it should always match. */
if( ( xt->handlers[i].name == NULL ||
- /* If it's not, compare. There should always be a name. */
+ /* If it's not, compare. There should always be a name. */
g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) &&
- /* If handler.parent == NULL, it's a match. */
+ /* If handler.parent == NULL, it's a match. */
( xt->handlers[i].parent == NULL ||
- /* If there's a parent node, see if the name matches. */
+ /* If there's a parent node, see if the name matches. */
( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 :
- /* If there's no parent, the handler should mention <root> as a parent. */
- g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
+ /* If there's no parent, the handler should mention <root> as a parent. */
+ strcmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
{
st = xt->handlers[i].func( node, xt->data );
@@ -259,6 +259,20 @@ void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth )
}
}
+struct xt_node *xt_from_string( const char *in )
+{
+ struct xt_parser *parser;
+ struct xt_node *ret;
+
+ parser = xt_new( NULL, NULL );
+ xt_feed( parser, in, strlen( in ) );
+ ret = parser->root;
+ parser->root = NULL;
+ xt_free( parser );
+
+ return ret;
+}
+
static void xt_to_string_real( struct xt_node *node, GString *str )
{
char *buf;
@@ -316,14 +330,18 @@ void xt_print( struct xt_node *node )
/* Indentation */
for( c = node; c->parent; c = c->parent )
- printf( "\t" );
+ printf( " " );
/* Start the tag */
printf( "<%s", node->name );
/* Print the attributes */
for( i = 0; node->attr[i].key; i ++ )
- printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) );
+ {
+ char *v = g_markup_escape_text( node->attr[i].value, -1 );
+ printf( " %s=\"%s\"", node->attr[i].key, v );
+ g_free( v );
+ }
/* /> in case there's really *nothing* inside this tag, otherwise
just >. */
@@ -343,7 +361,11 @@ void xt_print( struct xt_node *node )
{
for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ );
if( node->text[i] )
- printf( "%s", g_markup_escape_text( node->text, -1 ) );
+ {
+ char *v = g_markup_escape_text( node->text, -1 );
+ printf( "%s", v );
+ g_free( v );
+ }
}
if( node->children )
@@ -354,7 +376,7 @@ void xt_print( struct xt_node *node )
if( node->children )
for( c = node; c->parent; c = c->parent )
- printf( "\t" );
+ printf( " " );
/* Non-empty tag is now finished. */
printf( "</%s>\n", node->name );
@@ -464,6 +486,46 @@ struct xt_node *xt_find_node( struct xt_node *node, const char *name )
return node;
}
+/* More advanced than the one above, understands something like
+ ../foo/bar to find a subnode bar of a node foo which is a child
+ of node's parent. Pass the node directly, not its list of children. */
+struct xt_node *xt_find_path( struct xt_node *node, const char *name )
+{
+ while( name && *name && node )
+ {
+ char *colon, *slash;
+ int n;
+
+ if( ( slash = strchr( name, '/' ) ) )
+ n = slash - name;
+ else
+ n = strlen( name );
+
+ if( strncmp( name, "..", n ) == 0 )
+ {
+ node = node->parent;
+ }
+ else
+ {
+ node = node->children;
+
+ while( node )
+ {
+ if( g_strncasecmp( node->name, name, n ) == 0 ||
+ ( ( colon = strchr( node->name, ':' ) ) &&
+ g_strncasecmp( colon + 1, name, n ) == 0 ) )
+ break;
+
+ node = node->next;
+ }
+ }
+
+ name = slash ? slash + 1 : NULL;
+ }
+
+ return node;
+}
+
char *xt_find_attr( struct xt_node *node, const char *key )
{
int i;
@@ -549,6 +611,26 @@ void xt_add_child( struct xt_node *parent, struct xt_node *child )
}
}
+/* Same, but at the beginning. */
+void xt_insert_child( struct xt_node *parent, struct xt_node *child )
+{
+ struct xt_node *node, *last;
+
+ for( node = child; node; node = node->next )
+ {
+ if( node->parent != NULL )
+ {
+ /* ERROR CONDITION: They seem to have a parent already??? */
+ }
+
+ node->parent = parent;
+ last = node;
+ }
+
+ last->next = parent->children;
+ parent->children = child;
+}
+
void xt_add_attr( struct xt_node *node, const char *key, const char *value )
{
int i;