/** * Split a range into 3 parts to accommodate a tree-node * @param d the dom in question * @param n the node in the tree * @param r the out of tree range r to split up */ static void dom_breakup_range( dom *d, node *n, node *r ) { node *r2; if ( node_offset(n) > node_offset(r) ) { node_split( r, node_offset(n) ); r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r) ); //queue_push( d->q, node_to_range(r) ); node_dispose( r ); } else r2 = r; if ( node_end(r2)>node_end(n) ) { node *r3; node_split( r2, node_end(n) ); r3 = node_next_sibling(r2); node_detach_sibling(r3,r2); dom_store_range( d, node_to_range(r3) ); //queue_push( d->q, node_to_range(r3) ); node_dispose(r3); } dom_node_equals( d, n, r2 ); }
/** * Try to make the new node into a parent of the tree-node n. The problem * here is that we must include any siblings of n in r if they fit. * @param n the node above which to add the parent * @param r the new unattached node */ static void dom_make_parent( dom *d, node *n, node *r ) { node *parent = node_parent(n); node *prev = node_prec_sibling( n ); if ( parent==NULL ) printf("parent is NULL\n"); //fprintf( stderr,"n: %s %d:%d; r %s %d:%d\n",node_name(n),node_offset(n), // node_end(n),node_name(r),node_offset(r),node_end(r)); //node_debug_check_siblings( node_first_child(parent) ); while ( n != NULL && !node_follows(r,n) ) { node *next = node_next_sibling(n); if ( dom_nests(d,node_name(n),node_name(r)) ) { if ( range_encloses_node(n,r) || range_equals_node(n,r) ) { node_detach_sibling( n, prev ); node_add_child( r, n ); if ( node_overlaps_on_right(parent,r) ) { node_split( r, node_end(parent) ); node *r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); node_dispose( r2 ); } } else if ( node_overlaps_on_left(n,r) ) { node_split( n, node_end(r) ); node_detach_sibling( n, prev ); node_add_child( r, n ); break; } else break; } else { // split off the rest of r and and push it back // Q: what happens to r?? node *r2; node_split( r, node_offset(n) ); r2 = node_next_sibling( r ); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); //queue_push( d->q, node_to_range(r2) ); node_dispose( r2 ); break; } n = next; if ( n != NULL ) prev = node_prec_sibling( n ); } // make n's original parent the parent of r node_add_child( parent, r ); // node_debug_check_siblings( node_first_child(parent) ); }
/** * Dispose of the whole tree recursively. node_dispose just kills one node * @param n the node to start from */ static void dom_dispose_node( node *n ) { node *next = node_next_sibling( n ); node *child = node_first_child( n ); node_dispose( n ); if ( next != NULL ) dom_dispose_node( next ); if ( child != NULL ) dom_dispose_node( child ); }
int main( int argc, char **argv ) { node *root = node_create(0,0); int i,slen = strlen(str)-1; for ( i=0;i<slen;i++ ) { node *v = node_create(i,1); if ( find_child(root,str[i])==NULL ) node_add_child( root, v ); else node_dispose( v ); } for ( i=0;i<slen;i++ ) { node *v = find_child(root,str[i]); if ( v == NULL ) printf("couldn't find %c\n",str[i]); } node_dispose( root ); }
/** * Dispose of a node recursively, and thus the entire tree * @param v the node to dispose and its children. */ void node_dispose( node *v ) { node *child = v->children; while ( child != NULL ) { node *next = child->next; node_dispose( child ); child = next; } free( v ); }
/** * Write to the console details of the dropped node * @param d the dom in question * @param r the node we are dropping * @param n the parent node */ static void dom_drop_notify( dom *d, node *r, node *n ) { warning("dom: dropping %s at %d:%d - %s and %s incompatible\n", node_name(r),node_offset(r), node_end(r),node_html_name(r),node_html_name(n)); attribute *id = node_get_attribute( r, "id" ); if ( id != NULL ) { char *value = attribute_get_value( id ); if ( value[strlen(value)-1]=='b' ) printf( "aha! dropping id %s\n",value ); } node_dispose( r ); }
/** * Dispose of the hashtable and its children * @param htthe hashtable to dispose of */ void hashtable_dispose( hashtable *ht ) { int i = 0; for ( i=0;i<ht->nbuckets;i++ ) { struct bucket *b = ht->items[i]; while ( b != NULL ) { struct bucket *next = b->next; node_dispose( b->v ); free( b ); b = next; } } if ( ht->items != NULL ) free( ht->items ); free( ht ); }
/** * Handle overlap on the right of a tree-node * @param d the dom in question * @param n the node to test against * @param r the rogue who overlaps on the right */ static void dom_range_overlaps_right( dom *d, node *n, node *r ) { if ( dom_mostly_nests(d,node_name(n),node_name(r)) ) { node_split( n, node_offset(r) ); dom_add_node( d, node_next_sibling(n), r ); } else if ( dom_mostly_nests(d,node_name(r),node_name(n)) ) { node *r2; node_split( r, node_end(n) ); r2 = node_next_sibling(r); node_detach_sibling( r, NULL ); dom_store_range( d, node_to_range(r2) ); //queue_push( d->q, node_to_range(r2) ); node_dispose( r2 ); dom_add_node( d, n, r ); } else dom_drop_notify( d, r, n ); }
long calc_similars(const char* line) { root = build_tree( line ); int total = 0, multiple = 0, pplus = 0; if ( root != NULL ) { node *u = node_children(root); const char *p = line; node *next_u = NULL; while(*p) { next_u = NULL; while(u != NULL) { int nstart = node_start(u); if (line[nstart] == *p) { int end = node_end(u,e); pplus = end - nstart + (line[end] == 0 ? 0 : 1); next_u = node_children(u); } else if (node_is_leaf(u)){ multiple++; } else { multiple += node_num_children(node_children(u)); } u = node_next(u); } total += (p - line) * multiple; p += pplus; u = next_u; multiple = 0; } total += (p - line); node_dispose( root ); } return total; }
/** * Build the dom * @param d the dom object to build */ int dom_build( dom *d ) { int res = 1; while ( !queue_empty(d->q) ) { range *rx = queue_pop( d->q ); node *r = dom_range_to_node( d, rx ); if ( r != NULL ) { if ( node_end(r) <= d->text_len ) dom_add_node( d, d->root, r ); else { fprintf(stderr,"node range %d:%d > text length (%d)\n", node_offset(r),node_end(r), d->text_len ); node_dispose( r ); res = 0; break; } } } //matrix_dump( d->pm ); return res; }
/** * Dispose of a suffix tree. We don't own the text * @param st the suffixtree to dispose */ void suffixtree_dispose( suffixtree *st ) { node_dispose( st->root ); free( st ); }