/** * Initialise a matrix with a set of ranges that may be within one another * @param m the matrix in question * @param ranges the array of range object pointers */ void matrix_init( matrix *m, range_array *ranges ) { int i; int n_ranges = range_array_size( ranges ); matrix_queue *mq = matrix_queue_create(); for ( i=0;i<n_ranges;i++ ) { if ( !matrix_queue_add(mq,m,range_array_get(ranges,i)) ) break; } matrix_queue_dispose( mq ); m->inited = 1; }
static int dom_filter_ranges( dom *d, range_array *ranges ) { // first range must be root range *root = range_array_get(ranges,0); if ( root != NULL ) { if ( !queue_push(d->q,root) ) return 0; else { d->ranges = range_array_create(); if ( d->ranges != NULL ) { int i,num_ranges = range_array_size( ranges ); for ( i=1;i<num_ranges;i++ ) { range *r = range_array_get( ranges, i ); char *r_name = range_name( r ); hashset *pruned = matrix_get_lookup(d->pm); if ( hashset_contains(pruned,r_name) ) { css_rule *rule = hashmap_get( d->css_rules,r_name ); char *html_name = css_rule_get_element(rule); if ( range_html_name(r) != NULL|| range_set_html_name(r,html_name) ) { // this should duplicate the range range *r_dup = range_copy( r ); if ( r_dup == NULL || !dom_store_range(d,r_dup) ) { warning("dom: failed to push onto queue\n"); return 0; } } else { warning("dom: couldn't set html name for %s\n", r_name); return 0; } } } } return 1; } } else return 0; }
/** * Create a dom instance representing a document tree * @param text the text to represent * @param len the length of the text * @param properties the set of all used property names * @param ranges an array of ranges read from the markup file(s) * @param rules a read-only hashmap of css_rules indexed by property name * @param properties the set of property names we are interested in * @return the constructed dom */ dom *dom_create( const char *text, int len, range_array *ranges, hashmap *rules, hashset *properties ) { dom *d = calloc( 1, sizeof(dom)); if ( d != NULL ) { int p_size; char **array; d->text = text; d->text_len = len; d->css_rules = rules; p_size = hashset_size(properties); if ( p_size > 0 ) { char **props; array = calloc( p_size, sizeof(char*) ); if ( array == NULL ) { warning("dom: failed to allocate properties array\n"); dom_dispose( d ); return NULL; } hashset_to_array( properties, array ); if ( array_to_props(&p_size,array,rules,&props) ) { free( array ); array = NULL; d->pm = matrix_create( p_size, props ); free( props ); props = NULL; if ( d->pm == NULL ) { warning("dom: failed to create property matrix\n"); dom_dispose( d ); return NULL; } if ( range_array_size(ranges) > 0 ) { d->q = queue_create(); if ( d->q == NULL || !dom_filter_ranges(d,ranges) ) { dom_dispose( d ); return NULL; } else { range *r = queue_pop( d->q ); d->root = dom_range_to_node( d, r ); } d->buf = text_buf_create( (len*150)/100 ); if ( d->buf == NULL ) { dom_dispose( d ); d = NULL; } else { range_array_sort( d->ranges ); matrix_init( d->pm, d->ranges ); matrix_update_html( d->pm ); } } else { warning("dom: property list empty\n"); dom_dispose( d ); d = NULL; } } else { warning("dom: failed to build property array\n"); dom_dispose( d ); d = NULL; } } else { warning("dom: no properties specified. aborting.\n"); dom_dispose( d ); d = NULL; } } return d; }