Example #1
0
void
pop_dom_node(struct dom_stack *stack)
{
	struct dom_stack_state *state;
	int i;

	assert(stack);

	if (dom_stack_is_empty(stack))
		return;

	state = get_dom_stack_top(stack);
	if (state->immutable)
		return;

	if (call_dom_stack_callbacks(stack, state, DOM_STACK_POP)
	    || (stack->flags & DOM_STACK_FLAG_FREE_NODES))
		done_dom_node(state->node);

	stack->depth--;
	assert(stack->depth >= 0);

	for (i = 0; i < stack->contexts_size; i++) {
		struct dom_stack_context *context = stack->contexts[i];

		if (context->info->object_size) {
			void *state_data = get_dom_stack_state_data(context, state);

			memset(state_data, 0, context->info->object_size);
		}
	}

	memset(state, 0, sizeof(*state));
}
Example #2
0
/* Create a new parsing state by pushing a new text node containing the*/
static struct sgml_parsing_state *
init_sgml_parsing_state(struct sgml_parser *parser, struct dom_string *buffer)
{
	struct dom_stack_state *state;
	struct dom_node *node;

	node = init_dom_node(DOM_NODE_TEXT, buffer);
	if (!node || !push_dom_node(&parser->parsing, node))
		return NULL;

	state = get_dom_stack_top(&parser->parsing);

	return get_dom_stack_state_data(parser->parsing.contexts[0], state);
}
Example #3
0
/* Returns whether the node should be freed with done_dom_node(). */
static int
call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
			 enum dom_stack_action action)
{
	int free_node = 0;
	int i;

	for (i = 0; i < stack->contexts_size; i++) {
		struct dom_stack_context *context = stack->contexts[i];
		dom_stack_callback_T callback;

		assert(state->node->type < DOM_NODES); /* unsigned comparison */
		if_assert_failed {
			/* The node type is out of range for the
			 * callback arrays.  The node may have been
			 * corrupted or already freed.  Ignore
			 * free_node here because attempting to free
			 * the node would probably just corrupt things
			 * further.  */
			return 0;
		}

		if (action == DOM_STACK_PUSH)
			callback = context->info->push[state->node->type];
		else
			callback = context->info->pop[state->node->type];

		if (callback) {
			void *data = get_dom_stack_state_data(context, state);

			stack->current = context;
			switch (callback(stack, state->node, data)) {
			case DOM_CODE_FREE_NODE:
				free_node = 1;
				break;
			default:
				break;
			}
			stack->current = NULL;
		}
	}

	return free_node;
}
Example #4
0
/* 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;

	if (push_dom_node(stack, root) != DOM_CODE_OK)
		return;

	while (!dom_stack_is_empty(stack)) {
		struct dom_stack_state *state = get_dom_stack_top(stack);
		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) {
		case DOM_NODE_DOCUMENT:
			if (!list) list = node->data.document.children;
			break;

		case DOM_NODE_ELEMENT:
			if (!list) list = node->data.element.map;

			if (list == node->data.element.children) break;
			if (is_dom_node_list_member(list, wstate->index)
			    && list == node->data.element.map)
				break;

			list = node->data.element.children;
			break;

		case DOM_NODE_PROCESSING_INSTRUCTION:
			if (!list) list = node->data.proc_instruction.map;
			break;

		case DOM_NODE_DOCUMENT_TYPE:
			if (!list) list = node->data.document_type.entities;

			if (list == node->data.document_type.notations) break;
			if (is_dom_node_list_member(list, wstate->index)
			    && list == node->data.document_type.entities)
				break;

			list = node->data.document_type.notations;
			break;

		case DOM_NODE_ATTRIBUTE:
		case DOM_NODE_TEXT:
		case DOM_NODE_CDATA_SECTION:
		case DOM_NODE_COMMENT:
		case DOM_NODE_NOTATION:
		case DOM_NODE_DOCUMENT_FRAGMENT:
		case DOM_NODE_ENTITY_REFERENCE:
		case DOM_NODE_ENTITY:
		default:
			break;
		}

		/* Reset list state if it is a new list */
		if (list != wstate->list) {
			wstate->list  = list;
			wstate->index = 0;
		}

		/* If we have next child node */
		if (is_dom_node_list_member(list, wstate->index)) {
			struct dom_node *child = list->entries[wstate->index++];

			if (push_dom_node(stack, child) == DOM_CODE_OK)
				continue;
		}

		pop_dom_node(stack);
	}

	done_dom_stack_context(stack, context);
}