Esempio n. 1
0
/**
 * 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;
}