From 004f6c31e32e1297946935370bdc0be2fe5ae259 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sat, 5 Apr 2003 15:35:55 +0000 Subject: [project @ 2003-04-05 15:35:55 by bursa] Use hash-table to store CSS rules. svn path=/import/netsurf/; revision=113 --- css/css.c | 33 ++++++++++--------- css/css.h | 8 +++-- css/ruleset.c | 103 ++++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 98 insertions(+), 46 deletions(-) diff --git a/css/css.c b/css/css.c index 205fd8a83..d9d0c9967 100644 --- a/css/css.c +++ b/css/css.c @@ -1,5 +1,5 @@ /** - * $Id: css.c,v 1.1 2003/04/04 15:19:31 bursa Exp $ + * $Id: css.c,v 1.2 2003/04/05 15:35:55 bursa Exp $ */ #include @@ -74,12 +74,13 @@ const struct css_style css_blank_style = { void css_create(struct content *c) { + unsigned int i; LOG(("content %p", c)); c->data.css = xcalloc(1, sizeof(*c->data.css)); css_lex_init(&c->data.css->lexer); c->data.css->parser = css_parser_Alloc(malloc); - c->data.css->rule = 0; - c->data.css->last_rule = 0; + for (i = 0; i != HASH_SIZE; i++) + c->data.css->rule[i] = 0; } @@ -168,11 +169,12 @@ void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * sel unsigned int selectors, struct css_style * style) { struct node *r, *n, *m; - unsigned int i; + unsigned int hash, i; LOG(("stylesheet %p, selectors %u", stylesheet, selectors)); - - for (r = stylesheet->rule; r != 0; r = r->next) { + + hash = css_hash(selector[selectors - 1].element); + for (r = stylesheet->rule[hash]; r != 0; r = r->next) { i = selectors - 1; n = r; /* compare element */ @@ -218,14 +220,11 @@ void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * sel matched: /* TODO: sort by specificity */ LOG(("matched rule %p", r)); - css_dump_style(r->style); css_cascade(style, r->style); not_matched: } - - css_dump_style(style); } @@ -239,12 +238,6 @@ void css_parse_property_list(struct css_style * style, char * str) * dump a style */ -static void dump_length(const struct css_length * const length) -{ - LOG(("%g%s", length->value, - css_unit_name[length->unit])); -} - #define DUMP_LENGTH(pre, len, post) LOG((pre "%g%s" post, (len)->value, css_unit_name[(len)->unit])); void css_dump_style(const struct css_style * const style) @@ -389,6 +382,16 @@ void css_cascade(struct css_style * const style, const struct css_style * const } +unsigned int css_hash(const char *s) +{ + unsigned int z = 0; + for (; *s != 0; s++) + z += *s; + return z % HASH_SIZE; +} + + + #ifdef DEBUG int main() diff --git a/css/css.h b/css/css.h index 3b7844b5c..133f485eb 100644 --- a/css/css.h +++ b/css/css.h @@ -1,5 +1,5 @@ /** - * $Id: css.h,v 1.1 2003/04/04 15:19:31 bursa Exp $ + * $Id: css.h,v 1.2 2003/04/05 15:35:55 bursa Exp $ */ #ifndef _NETSURF_CSS_CSS_H_ @@ -136,11 +136,12 @@ struct node { #include "netsurf/css/scanner.h" +#define HASH_SIZE 47 + struct css_stylesheet { yyscan_t lexer; void *parser; - struct node *rule; - struct node *last_rule; + struct node *rule[HASH_SIZE]; }; #endif @@ -166,6 +167,7 @@ void css_free_node(struct node *node); void css_add_ruleset(struct css_stylesheet *stylesheet, struct node *selector, struct node *declaration); +unsigned int css_hash(const char *s); void css_parser_Trace(FILE *TraceFILE, char *zTracePrompt); void *css_parser_Alloc(void *(*mallocProc)(int)); diff --git a/css/ruleset.c b/css/ruleset.c index e22a188b8..32bb235a3 100644 --- a/css/ruleset.c +++ b/css/ruleset.c @@ -1,5 +1,5 @@ /** - * $Id: ruleset.c,v 1.1 2003/04/04 15:19:31 bursa Exp $ + * $Id: ruleset.c,v 1.2 2003/04/05 15:35:55 bursa Exp $ */ #include @@ -28,6 +28,7 @@ struct font_size_entry { }; +static int compare_selectors(struct node *n0, struct node *n1); static int parse_length(struct css_length * const length, const struct node * const v); static colour parse_colour(const struct node * const v); static void parse_background_color(struct css_style * const s, const struct node * const v); @@ -102,40 +103,86 @@ void css_add_ruleset(struct css_stylesheet *stylesheet, struct node *selector, struct node *declaration) { - struct node *n, *last; + struct node *n, *sel, *next_sel; struct css_style *style; - - /* construct the struct css_style */ - style = xcalloc(1, sizeof(*style)); - memcpy(style, &css_blank_style, sizeof(*style)); - - for (n = declaration; n != 0; n = n->next) { - struct property_entry *p; - assert(n->type == NODE_DECLARATION && n->data != 0 && n->left != 0); - p = bsearch(n->data, property_table, - sizeof(property_table) / sizeof(property_table[0]), - sizeof(property_table[0]), strcasecmp); - if (p == 0) - continue; - p->parse(style, n->left); + unsigned int hash; + + for (sel = selector; sel != 0; sel = next_sel) { + next_sel = sel->next; + + /* check if this selector is already present */ + hash = css_hash(sel->data); + for (n = stylesheet->rule[hash]; n != 0; n = n->next) + if (compare_selectors(sel, n)) + break; + if (n == 0) { + /* not present: construct a new struct css_style */ + style = xcalloc(1, sizeof(*style)); + memcpy(style, &css_blank_style, sizeof(*style)); + sel->style = style; + sel->next = stylesheet->rule[hash]; + stylesheet->rule[hash] = sel; + } else { + /* already exists: augument existing style */ + style = n->style; + sel->next = 0; + css_free_node(sel); + } + + /* fill in the declarations */ + for (n = declaration; n != 0; n = n->next) { + struct property_entry *p; + assert(n->type == NODE_DECLARATION && n->data != 0 && n->left != 0); + p = bsearch(n->data, property_table, + sizeof(property_table) / sizeof(property_table[0]), + sizeof(property_table[0]), strcasecmp); + if (p == 0) + continue; + p->parse(style, n->left); + } } +} - /*css_dump_style(style);*/ - /* add selectors to the stylesheet */ - /* TODO: merge with identical selector */ - for (n = selector; n != 0; n = n->next) { - n->style = style; - last = n; +int compare_selectors(struct node *n0, struct node *n1) +{ + struct node *m0, *m1; + unsigned int count0, count1; + + /* compare element name */ + if (!((n0->data == 0 && n1->data == 0) || + (n0->data != 0 && n1->data != 0 && strcasecmp(n0->data, n1->data) == 0))) + return 0; + + if (n0->comb != n1->comb) + return 0; + + /* compare classes and ids */ + for (m0 = n0->left; m0 != 0; m0 = m0->next) + count0++; + for (m1 = n1->left; m1 != 0; m1 = m1->next) + count1++; + if (count0 != count1) + return 0; + for (m0 = n0->left; m0 != 0; m0 = m0->next) { + int found = 0; + for (m1 = n1->left; m1 != 0; m1 = m1->next) { + /* TODO: should this be case sensitive for IDs? */ + if (m0->type == m1->type && strcasecmp(m0->data, m1->data) == 0) { + found = 1; + break; + } + } + if (!found) + return 0; } - if (stylesheet->rule == 0) - stylesheet->rule = selector; - else - stylesheet->last_rule->next = selector; - stylesheet->last_rule = last; -} + /* compare ancestors */ + if (n0->comb == COMB_NONE) + return 1; + return compare_selectors(n0->right, n1->right); +} -- cgit v1.2.3