1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-07-04 02:35:29 +00:00

Make walk_dom_nodes() use a stack context; reduces the DOM stack state size

This commit is contained in:
Jonas Fonseca 2005-12-27 06:04:01 +01:00 committed by Jonas Fonseca
parent a4831fef2d
commit 9e7dfb1ddf
2 changed files with 63 additions and 15 deletions

View File

@ -289,18 +289,71 @@ search_dom_stack(struct dom_stack *stack, enum dom_node_type type,
return NULL;
}
struct dom_stack_walk_state {
/* Used for recording which node list are currently being 'decended'
* into. E.g. whether we are iterating all child elements or attributes
* of an element. */
struct dom_node_list *list;
/* The index (in the list above) which are currently being handled. */
size_t index;
};
static struct dom_stack_context_info dom_stack_walk_context_info = {
/* Object size: */ sizeof(struct dom_stack_walk_state),
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ NULL,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ NULL,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ NULL,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ NULL,
/* DOM_NODE_CDATA_SECTION */ NULL,
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
/* DOM_NODE_ENTITY */ NULL,
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
/* DOM_NODE_COMMENT */ NULL,
/* DOM_NODE_DOCUMENT */ NULL,
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
/* DOM_NODE_NOTATION */ NULL,
}
};
/* FIXME: Instead of walking all nodes in the tree only visit those which are
* of actual interest to the contexts on the stack. */
void
walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
{
struct dom_stack_context *context;
assert(root && stack);
context = add_dom_stack_context(stack, NULL, &dom_stack_walk_context_info);
if (!context)
return;
push_dom_node(stack, root);
while (!dom_stack_is_empty(stack)) {
struct dom_stack_state *state = get_dom_stack_top(stack);
struct dom_node_list *list = state->list;
struct dom_stack_walk_state *wstate = get_dom_stack_state_data(context, state);
struct dom_node_list *list = wstate->list;
struct dom_node *node = state->node;
switch (node->type) {
@ -312,7 +365,7 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
if (!list) list = node->data.element.map;
if (list == node->data.element.children) break;
if (is_dom_node_list_member(list, state->index)
if (is_dom_node_list_member(list, wstate->index)
&& list == node->data.element.map)
break;
@ -327,7 +380,7 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
if (!list) list = node->data.document_type.entities;
if (list == node->data.document_type.notations) break;
if (is_dom_node_list_member(list, state->index)
if (is_dom_node_list_member(list, wstate->index)
&& list == node->data.document_type.entities)
break;
@ -347,14 +400,14 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
}
/* Reset list state if it is a new list */
if (list != state->list) {
state->list = list;
state->index = 0;
if (list != wstate->list) {
wstate->list = list;
wstate->index = 0;
}
/* If we have next child node */
if (is_dom_node_list_member(list, state->index)) {
struct dom_node *child = list->entries[state->index++];
if (is_dom_node_list_member(list, wstate->index)) {
struct dom_node *child = list->entries[wstate->index++];
if (push_dom_node(stack, child))
continue;
@ -362,6 +415,8 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
pop_dom_node(stack);
}
done_dom_stack_context(stack, context);
}

View File

@ -14,13 +14,6 @@ typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void
struct dom_stack_state {
struct dom_node *node;
/* Used for recording which node list are currently being 'decended'
* into. E.g. whether we are iterating all child elements or attributes
* of an element. */
struct dom_node_list *list;
/* The index (in the list above) which are currently being handled. */
size_t index;
/* The depth of the state in the stack. This is amongst other things
* used to get the state object data. */
unsigned int depth;