css->flags = label->flags;
if (css->text) {
- css->last_key = j < 0 ? 0 : j;
- css->last_key_end = k;
+ if (j < 0)
+ j = 0;
- scf_logi("css selector '%s', last key: %.*s\n", css->text->data,
- (int)(css->last_key_end - css->last_key),
- css->text->data + css->last_key);
+ switch (css->text->data[j]) {
+ case '#':
+ case '.':
+ case '[':
+ case ':':
+ j++;
+ css->key_type = css->type;
+ break;
+ case ' ':
+ case '>':
+ case '+':
+ case '~':
+ j++;
+ default:
+ c = css->text->data[k];
+ css->text->data[k] = '\0';
+
+ label = __html_find_label(css->text->data + j);
+ css->text->data[k] = c;
+
+ css->key_type = label->type;
+ break;
+ };
+
+ css->last_key = j;
+ css->last_key_end = k;
}
return 0;
}
copy->keys = attr->keys;
copy->flags = attr->flags;
- if (h->attrs[i])
- abc_attr_free(h->attrs[i]);
+ if (h->cache_attrs[i])
+ abc_attr_free(h->cache_attrs[i]);
- h->attrs[i] = copy;
+ h->cache_attrs[i] = copy;
}
return 0;
for (l = scf_list_head(&obj->css); l != scf_list_sentinel(&obj->css); l = scf_list_next(l)) {
css = scf_list_data(l, css_rule_t, list);
- h = &(html->css->hash[css->type]);
+ if (css->type < ABC_HTML_NB) {
+ h = &(html->css->tag_selectors[css->type][0]);
+
+ scf_list_add_tail(&h->rules, &css->hash);
+ } else if (ABC_CSS_COMBINATOR == css->type) {
+ h = &(html->css->tag_selectors[css->key_type][1]);
+
+ scf_list_add_tail(&h->rules, &css->hash);
+ } else if (ABC_CSS_PSE_ELEMENT == css->type) {
+ assert(css->key_type < ABC_HTML_NB);
+
+ h = &(html->css->pse_selectors[css->key_type][0]);
+
+ scf_list_add_tail(&h->rules, &css->hash);
+ } else if (ABC_CSS_PSE_CLASS == css->type) {
+ assert(css->key_type < ABC_HTML_NB);
- scf_list_add_tail(&h->rules, &css->hash);
+ h = &(html->css->pse_selectors[css->key_type][1]);
- css_hash_update_attrs(h, css);
+ scf_list_add_tail(&h->rules, &css->hash);
+ } else {
+ int pse_type = ABC_CSS_COMBINATOR;
+ int key_type = css->key_type;
+
+ if (':' == css->text->data[css->last_key_end])
+ {
+ if (':' == css->text->data[css->last_key_end + 1])
+ pse_type = ABC_CSS_PSE_ELEMENT;
+ else
+ pse_type = ABC_CSS_PSE_CLASS;
+ }
+
+ if (ABC_CSS_ATTR == css->type) {
+ if (key_type < ABC_HTML_NB)
+ h = &(html->css->attr_selectors[key_type][pse_type - ABC_CSS_COMBINATOR]);
+ else
+ h = &(html->css->attr_selectors[ABC_HTML_NB][pse_type - ABC_CSS_COMBINATOR]);
+
+ scf_list_add_tail(&h->rules, &css->hash);
+ } else {
+ if (key_type >= ABC_HTML_NB)
+ {
+ int c = css->text->data[css->last_key_end];
+
+ css->text->data[css->last_key_end] = '\0';
+ uint32_t hash = elf_new_hash(css->text->data + css->last_key);
+ css->text->data[css->last_key_end] = c;
+
+ key_type = hash % CSS_HASH_NB + ABC_HTML_NB;
+ scf_logi("key_type: %d, css->key_type: %d, pse_type - ABC_CSS_COMBINATOR: %d\n",
+ key_type, css->key_type, pse_type - ABC_CSS_COMBINATOR);
+ }
+
+ if (ABC_CSS_CLASS == css->type)
+ h = &(html->css->class_selectors[key_type][pse_type - ABC_CSS_COMBINATOR]);
+ else
+ h = &(html->css->id_selectors [key_type][pse_type - ABC_CSS_COMBINATOR]);
+
+ scf_list_add_tail(&h->rules, &css->hash);
+ }
+ }
+
+ if (css->type <= ABC_CSS_COMBINATOR)
+ css_hash_update_attrs(h, css);
+ }
+
+ return 0;
+}
+
+int css_hash_use_caches(css_hash_t* h, abc_obj_t* obj)
+{
+ int j;
+ for (j = 0; j < sizeof(h->cache_attrs) / sizeof(h->cache_attrs[0]); j++) {
+ abc_attr_t* attr = h->cache_attrs[j];
+ if (attr)
+ __css_set_attr(obj, attr);
+ }
+
+ return 0;
+}
+
+int css_hash_use_rules(css_hash_t* h, abc_obj_t* obj)
+{
+ scf_list_t* l;
+ css_rule_t* r;
+
+ for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); l = scf_list_next(l)) {
+ r = scf_list_data(l, css_rule_t, hash);
+
+ __css_use_complex(r, obj);
+ }
+
+ return 0;
+}
+
+int css_hash_use_selectors(css_hash_t selectors[][ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR], int attr_type, int hash_max, abc_obj_t* obj)
+{
+ css_hash_t* h;
+ abc_attr_t* attr = abc_obj_get_attr(obj, attr_type);
+
+ int i;
+ int j = -1;
+
+ if (attr && attr->value && attr->value > 0)
+ j = elf_new_hash(attr->value->data) % hash_max;
+
+ for (i = 0; i < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; i++) {
+
+ h = &(selectors[obj->type][i]);
+ css_hash_use_rules(h, obj);
+
+ if (j >= 0) {
+ h = &(selectors[ABC_HTML_NB + j][i]);
+ css_hash_use_rules(h, obj);
+ }
+ }
+
+ return 0;
+}
+
+static int __css_use_attr_selectors(abc_css_t* css, abc_obj_t* obj)
+{
+ css_hash_t* h0;
+ css_hash_t* h1;
+ int i;
+
+ for (i = 0; i < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; i++) {
+
+ h0 = &(css->id_selectors[obj->type ][i]);
+ h1 = &(css->id_selectors[ABC_HTML_NB][i]);
+
+ css_hash_use_rules(h0, obj);
+ css_hash_use_rules(h1, obj);
}
return 0;
int64_t tv0 = gettime();
if (html->css) {
- css_hash_t* h = &(html->css->hash[obj->type]);
-
- int i;
- for (i = 0; i < sizeof(h->attrs) / sizeof(h->attrs[0]); i++) {
- attr = h->attrs[i];
- if (attr)
- __css_set_attr(obj, attr);
- }
+ css_hash_use_caches(&(html->css->tag_selectors[obj->type][0]), obj);
+ css_hash_use_caches(&(html->css->tag_selectors[obj->type][1]), obj);
- for (i = ABC_CSS_COMBINATOR; i < ABC_CSS_SELECTOR_NB; i++)
- {
- h = &(html->css->hash[i]);
+ css_hash_use_rules(&(html->css->pse_selectors[obj->type][0]), obj);
+ css_hash_use_rules(&(html->css->pse_selectors[obj->type][1]), obj);
- for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); l = scf_list_next(l)) {
- css = scf_list_data(l, css_rule_t, hash);
+ __css_use_attr_selectors(html->css, obj);
- __css_use_complex(css, obj);
- }
- }
+ css_hash_use_selectors(html->css->class_selectors, ABC_CSS_CLASS, CSS_HASH_NB, obj);
+ css_hash_use_selectors(html->css->id_selectors, ABC_CSS_ID, CSS_HASH_NB, obj);
}
// for inline css below
}
}
+void css_hash_free(css_hash_t* h)
+{
+ scf_list_t* l;
+ css_rule_t* r;
+ int k;
+
+ for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); ) {
+ r = scf_list_data(l, css_rule_t, hash);
+ l = scf_list_next(l);
+
+ scf_list_del(&r->hash);
+ }
+
+ for (k = 0; k < sizeof(h->cache_attrs) / sizeof(h->cache_attrs); k++) {
+ if (h->cache_attrs[k])
+ abc_attr_free(h->cache_attrs[k]);
+ }
+}
+
void abc_css_free(abc_css_t* css)
{
if (css) {
- scf_list_t* l;
- css_rule_t* r;
css_hash_t* h;
int i;
int j;
- for (i = 0; i < ABC_CSS_SELECTOR_NB; i++) {
- h = &(css->hash[i]);
-
- for (l = scf_list_head(&h->rules); l != scf_list_sentinel(&h->rules); ) {
- r = scf_list_data(l, css_rule_t, hash);
- l = scf_list_next(l);
-
- scf_list_del(&r->hash);
+ for (i = 0; i < ABC_HTML_NB; i++) {
+ for (j = 0; j < 2; j++) {
+ css_hash_free(&(css->tag_selectors[i][j]));
+ css_hash_free(&(css->pse_selectors[i][j]));
}
+ }
+
+ for (i = 0; i < ABC_HTML_NB + 1; i++) {
+ for (j = 0; j < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; j++)
+ css_hash_free(&(css->attr_selectors[i][j]));
+ }
- for (j = 0; j < sizeof(h->attrs) / sizeof(h->attrs); j++) {
- if (h->attrs[j])
- abc_attr_free(h->attrs[j]);
+ for (i = 0; i < ABC_HTML_NB + CSS_HASH_NB; i++) {
+ for (j = 0; j < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; j++) {
+ css_hash_free(&(css->class_selectors[i][j]));
+ css_hash_free(&(css->id_selectors [i][j]));
}
}
return NULL;
int i;
- for (i = 0; i < ABC_CSS_SELECTOR_NB; i++)
- scf_list_init(&(css->hash[i].rules));
+ int j;
+ for (i = 0; i < ABC_HTML_NB; i++) {
+ for (j = 0; j < 2; j++) {
+ scf_list_init(&(css->tag_selectors[i][j].rules));
+ scf_list_init(&(css->pse_selectors[i][j].rules));
+ }
+ }
+
+ for (i = 0; i < ABC_HTML_NB + 1; i++) {
+ for (j = 0; j < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; j++)
+ scf_list_init(&(css->attr_selectors[i][j].rules));
+ }
+
+ for (i = 0; i < ABC_HTML_NB + CSS_HASH_NB; i++) {
+ for (j = 0; j < ABC_CSS_PSE_NB - ABC_CSS_COMBINATOR; j++) {
+ scf_list_init(&(css->class_selectors[i][j].rules));
+ scf_list_init(&(css->id_selectors [i][j].rules));
+ }
+ }
return css;
}