From 07fc481607c3477cb0cdc1d48d5d4195e7acc384 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 00:11:25 +0100 Subject: [PATCH 1/6] match_attribute_selectors(): Factor out matching of values to own function --- src/document/dom/select.c | 81 ++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index 40638bd92..9fcf81be8 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -16,6 +16,8 @@ #include "util/string.h" +/* Selector parsing: */ + /* Maps the content of a scanner token to a pseudo-class or -element ID. */ static enum dom_select_pseudo get_dom_select_pseudo(struct scanner_token *token) @@ -555,6 +557,8 @@ done_dom_select(struct dom_select *select) } +/* DOM node selection: */ + /* This struct stores data related to the 'application' of a DOM selector * on a DOM tree or stream. */ struct dom_select_data { @@ -605,6 +609,47 @@ get_child_dom_select_node(struct dom_select_node *selector, #define has_attribute_match(selector, name) \ ((selector)->match.attribute & (name)) +static int +match_attribute_value(struct dom_select_node *selector, struct dom_node *node) +{ + struct dom_string *selvalue = &selector->node.data.attribute.value; + struct dom_string *value = &attr->data.attribute.value; + + /* The attribute selector value should atleast be contained in the + * attribute value. */ + if (value->length < selvalue->length) + return 0; + + /* FIXME: Combine the 3 following to use an offset to specify where in + * value, selvalue should match. */ + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_EXACT) + && dom_string_casecmp(value, selvalue)) + return 0; + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_BEGIN)) + return 0; + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_END)) + return 0; + + /* FIXME: Combine the 3 following to simply strstr()-search the value + * and based on a char group check if it is separated either by + * begining, end or the values in the char group: '-' for + * DOM_SELECT_ATTRIBUTE_HYPHEN_LIST, etc. */ + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_SPACE_LIST)) + return 0; + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_HYPHEN_LIST)) + return 0; + + if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_CONTAINS)) + return 0; + + return 1; +} + /* Match the attribute of an element @node against attribute selector nodes * of a given @base. */ static int @@ -629,8 +674,6 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node) foreach_dom_node (selnodes, selnode, index) { struct dom_select_node *selector = (void *) selnode; struct dom_node *attr; - struct dom_string *value; - struct dom_string *selvalue; if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_ID)) { size_t idindex; @@ -656,39 +699,7 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node) if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_ANY)) continue; - value = &attr->data.attribute.value; - selvalue = &selnode->data.attribute.value; - - /* The attribute selector value should atleast be contained in - * the attribute value. */ - if (value->length < selvalue->length) - return 0; - - /* FIXME: Combine the 3 following to use an offset to specify - * where in value, selvalue should match. */ - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_EXACT) - && dom_string_casecmp(value, selvalue)) - return 0; - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_BEGIN)) - return 0; - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_END)) - return 0; - - /* FIXME: Combine the 3 following to simply strstr()-search the - * value and based on a char group check if it is separated - * either by begining, end or the values in the char group: - * '-' for DOM_SELECT_ATTRIBUTE_HYPHEN_LIST, etc. */ - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_SPACE_LIST)) - return 0; - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_HYPHEN_LIST)) - return 0; - - if (has_attribute_match(selector, DOM_SELECT_ATTRIBUTE_CONTAINS)) + if (!match_attribute_value(selector, attr)) return 0; } From 12d34fd1332a89aada3c4ab76cd96d7ea9c7dde1 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 00:51:57 +0100 Subject: [PATCH 2/6] Factor out code to new match_element_selector() 'Twill make it easier to do the logic. --- src/document/dom/select.c | 103 +++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index 9fcf81be8..f7e03869d 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -711,6 +711,61 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node) #define get_dom_select_data(stack) ((stack)->current->data) +static int +match_element_selector(struct dom_select_node *selector, struct dom_node *node) +{ + /* Match the node. */ + if (!has_element_match(selector, DOM_SELECT_ELEMENT_UNIVERSAL) + && dom_node_casecmp(&selector->node, node)) + return 0; + + switch (get_element_relation(selector)) { + case DOM_SELECT_RELATION_DIRECT_CHILD: /* E > F */ + /* node->parent */ + /* Check all states to see if node->parent is there + * and for the right reasons. */ + break; + + case DOM_SELECT_RELATION_DIRECT_ADJACENT: /* E + F */ + /* Get preceding node to see if it is on the stack. */ + break; + + case DOM_SELECT_RELATION_INDIRECT_ADJACENT: /* E ~ F */ + /* Check all states with same depth? */ + break; + + case DOM_SELECT_RELATION_DESCENDANT: /* E F */ + default: + break; + } + + /* Root node are rooted at the don't have parent nodes. */ + if (has_element_match(selector, DOM_SELECT_ELEMENT_ROOT) + && node->parent) + return 0; + + if (has_element_match(selector, DOM_SELECT_ELEMENT_EMPTY) + && node->data.element.map->size > 0) + return 0; + + if (has_element_match(selector, DOM_SELECT_ELEMENT_NTH_CHILD)) { + /* FIXME */ + return 0; + } + + if (has_element_match(selector, DOM_SELECT_ELEMENT_NTH_TYPE)) { + /* FIXME */ + return 0; + } + + /* Check attribute selectors. */ + if (selector->node.data.element.map + && !match_attribute_selectors(selector, node)) + return 0; + + return 1; +} + /* Matches an element node being visited against the current selector stack. */ static void dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *data) @@ -728,53 +783,7 @@ dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *da * on the select_data->stack, cache what select nodes was * matches so that it is only checked once. */ - /* Match the node. */ - if (!has_element_match(selector, DOM_SELECT_ELEMENT_UNIVERSAL) - && dom_node_casecmp(&selector->node, node)) - continue; - - switch (get_element_relation(selector)) { - case DOM_SELECT_RELATION_DIRECT_CHILD: /* E > F */ - /* node->parent */ - /* Check all states to see if node->parent is there - * and for the right reasons. */ - break; - - case DOM_SELECT_RELATION_DIRECT_ADJACENT: /* E + F */ - /* Get preceding node to see if it is on the stack. */ - break; - - case DOM_SELECT_RELATION_INDIRECT_ADJACENT: /* E ~ F */ - /* Check all states with same depth? */ - break; - - case DOM_SELECT_RELATION_DESCENDANT: /* E F */ - default: - break; - } - - /* Roots don't have parent nodes. */ - if (has_element_match(selector, DOM_SELECT_ELEMENT_ROOT) - && node->parent) - continue; - - if (has_element_match(selector, DOM_SELECT_ELEMENT_EMPTY) - && node->data.element.map->size > 0) - continue; - - if (has_element_match(selector, DOM_SELECT_ELEMENT_NTH_CHILD)) { - /* FIXME */ - continue; - } - - if (has_element_match(selector, DOM_SELECT_ELEMENT_NTH_TYPE)) { - /* FIXME */ - continue; - } - - /* Check attribute selectors. */ - if (selector->node.data.element.map - && !match_attribute_selectors(selector, node)) + if (!match_element_selector(selector, node)) continue; WDBG("Matched element: %.*s.", node->string.length, node->string.string); From 4d6223f6a455b34c1d2258b332421644dff3136e Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 00:52:52 +0100 Subject: [PATCH 3/6] Oops, compile fix --- src/document/dom/select.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index f7e03869d..fc8a96822 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -613,7 +613,7 @@ static int match_attribute_value(struct dom_select_node *selector, struct dom_node *node) { struct dom_string *selvalue = &selector->node.data.attribute.value; - struct dom_string *value = &attr->data.attribute.value; + struct dom_string *value = &node->data.attribute.value; /* The attribute selector value should atleast be contained in the * attribute value. */ From 755108cf957e081c39c0e2be6d70cef4a0d34911 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 00:53:31 +0100 Subject: [PATCH 4/6] Tidyup --- src/document/dom/select.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index fc8a96822..eda888619 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -714,7 +714,6 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node) static int match_element_selector(struct dom_select_node *selector, struct dom_node *node) { - /* Match the node. */ if (!has_element_match(selector, DOM_SELECT_ELEMENT_UNIVERSAL) && dom_node_casecmp(&selector->node, node)) return 0; @@ -766,6 +765,7 @@ match_element_selector(struct dom_select_node *selector, struct dom_node *node) return 1; } + /* Matches an element node being visited against the current selector stack. */ static void dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *data) @@ -934,6 +934,7 @@ static struct dom_stack_context_info dom_select_data_context_info = { } }; + struct dom_node_list * select_dom_nodes(struct dom_select *select, struct dom_node *root) { From 3ea1b30fd6b08ed3b4b139c1d87d0530e7303a83 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 00:59:56 +0100 Subject: [PATCH 5/6] Fix matching of the :root structural pseudo-class Root nodes either have no parents or are the single child of the document node. --- src/document/dom/select.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index eda888619..1bbaed9d1 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -738,10 +738,14 @@ match_element_selector(struct dom_select_node *selector, struct dom_node *node) break; } - /* Root node are rooted at the don't have parent nodes. */ + /* Root nodes either have no parents or are the single child of the + * document node. */ if (has_element_match(selector, DOM_SELECT_ELEMENT_ROOT) - && node->parent) - return 0; + && node->parent) { + if (node->parent->type != DOM_NODE_DOCUMENT + || node->parent->children->size > 1) + return 0; + } if (has_element_match(selector, DOM_SELECT_ELEMENT_EMPTY) && node->data.element.map->size > 0) From 8d30613a7fa0f0a2088fb1007afed49435cdd39f Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 23 Dec 2005 01:03:39 +0100 Subject: [PATCH 6/6] The child node list can be NULL when matching for the :empty pseudo-class Also use the children node list and not the attribute list (aka the map). --- src/document/dom/select.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/document/dom/select.c b/src/document/dom/select.c index 1bbaed9d1..c179e97ac 100644 --- a/src/document/dom/select.c +++ b/src/document/dom/select.c @@ -714,6 +714,8 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node) static int match_element_selector(struct dom_select_node *selector, struct dom_node *node) { + assert(node && node->type == DOM_NODE_ELEMENT); + if (!has_element_match(selector, DOM_SELECT_ELEMENT_UNIVERSAL) && dom_node_casecmp(&selector->node, node)) return 0; @@ -748,7 +750,8 @@ match_element_selector(struct dom_select_node *selector, struct dom_node *node) } if (has_element_match(selector, DOM_SELECT_ELEMENT_EMPTY) - && node->data.element.map->size > 0) + && node->data.element.children + && node->data.element.children->size > 0) return 0; if (has_element_match(selector, DOM_SELECT_ELEMENT_NTH_CHILD)) {