1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-28 01:35:32 +00:00

Move the state_objects to the DOM stack contexts

This way all contexts are now separated, almost.
This commit is contained in:
Jonas Fonseca 2005-12-21 04:38:04 +01:00 committed by Jonas Fonseca
parent 910c51abaf
commit f8d48e81eb
5 changed files with 47 additions and 37 deletions

View File

@ -621,7 +621,8 @@ static void
render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
struct sgml_parser_state *pstate = data;
struct dom_stack_state *state = get_dom_stack_top(stack);
struct sgml_parser_state *pstate = get_dom_stack_state_data(stack->contexts, state);
struct scanner_token *token = &pstate->end_token;
unsigned char *string = token->string;
int length = token->length;
@ -730,6 +731,7 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
}
static struct dom_stack_context_info dom_source_renderer_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,

View File

@ -742,7 +742,7 @@ dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *dat
struct dom_select_node *selector = (void *) state->node;
struct dom_select_state *select_state;
select_state = get_dom_stack_state_data(stack, state);
select_state = get_dom_stack_state_data(stack->current, state);
if (select_state->node == node) {
pop_dom_state(stack, state);
WDBG("Remove element.");
@ -788,6 +788,7 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
}
static struct dom_stack_context_info dom_select_context_info = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
@ -823,6 +824,7 @@ static struct dom_stack_context_info dom_select_context_info = {
};
static struct dom_stack_context_info dom_select_data_context_info = {
/* Object size: */ sizeof(struct dom_select_state),
/* Push: */
{
/* */ NULL,
@ -862,7 +864,6 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
{
struct dom_select_data select_data;
struct dom_stack stack;
size_t obj_size = sizeof(struct dom_select_state);
memset(&select_data, 0, sizeof(select_data));
@ -872,7 +873,7 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
add_dom_stack_context(&stack, &select_data,
&dom_select_context_info);
init_dom_stack(&select_data.stack, obj_size, 1);
init_dom_stack(&select_data.stack, 0, 1);
add_dom_stack_context(&stack, &select_data,
&dom_select_data_context_info);

View File

@ -37,17 +37,17 @@ realloc_dom_stack_context(struct dom_stack_context **contexts, size_t size)
}
static inline unsigned char *
realloc_dom_stack_state_objects(struct dom_stack *stack)
realloc_dom_stack_state_objects(struct dom_stack_context *context, size_t depth)
{
#ifdef DEBUG_MEMLEAK
return mem_align_alloc__(__FILE__, __LINE__, (void **) &stack->state_objects,
stack->depth, stack->depth + 1,
stack->object_size,
return mem_align_alloc__(__FILE__, __LINE__, (void **) &context->state_objects,
depth, depth + 1,
context->info->object_size,
DOM_STACK_STATE_GRANULARITY);
#else
return mem_align_alloc__((void **) &stack->state_objects,
stack->depth, stack->depth + 1,
stack->object_size,
return mem_align_alloc__((void **) &context->state_objects,
depth, depth + 1,
context->info->object_size,
DOM_STACK_STATE_GRANULARITY);
#endif
}
@ -59,18 +59,22 @@ init_dom_stack(struct dom_stack *stack, size_t object_size, int keep_nodes)
memset(stack, 0, sizeof(*stack));
stack->object_size = object_size;
stack->keep_nodes = !!keep_nodes;
}
void
done_dom_stack(struct dom_stack *stack)
{
int i;
assert(stack);
for (i = 0; i < stack->contexts_size; i++) {
mem_free_if(stack->contexts[i].state_objects);
}
mem_free_if(stack->contexts);
mem_free_if(stack->states);
mem_free_if(stack->state_objects);
memset(stack, 0, sizeof(*stack));
}
@ -98,13 +102,11 @@ static void
call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
enum dom_stack_action action)
{
/* FIME: Variable stack data, so the parse/selector/renderer/etc. can
* really work in parallel. */
void *state_data = get_dom_stack_state_data(stack, state);
int i;
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
void *state_data = get_dom_stack_state_data(context, state);
dom_stack_callback_T callback;
if (action == DOM_STACK_PUSH)
@ -124,6 +126,7 @@ struct dom_node *
push_dom_node(struct dom_stack *stack, struct dom_node *node)
{
struct dom_stack_state *state;
int i;
assert(stack && node);
assert(0 < node->type && node->type < DOM_NODES);
@ -140,18 +143,17 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
state += stack->depth;
if (stack->object_size) {
unsigned char *state_objects;
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
state_objects = realloc_dom_stack_state_objects(stack);
if (!state_objects) {
if (context->info->object_size
&& !realloc_dom_stack_state_objects(context, stack->depth)) {
done_dom_node(node);
return NULL;
}
state->depth = stack->depth;
}
state->depth = stack->depth;
state->node = node;
/* Grow the state array to the new depth so the state accessors work
@ -166,6 +168,7 @@ static int
do_pop_dom_node(struct dom_stack *stack, struct dom_stack_state *parent)
{
struct dom_stack_state *state;
int i;
assert(stack && !dom_stack_is_empty(stack));
@ -181,10 +184,14 @@ do_pop_dom_node(struct dom_stack *stack, struct dom_stack_state *parent)
stack->depth--;
assert(stack->depth >= 0);
if (stack->object_size) {
void *state_data = get_dom_stack_state_data(stack, state);
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
memset(state_data, 0, stack->object_size);
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));

View File

@ -11,6 +11,7 @@ struct dom_stack;
typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
struct dom_stack_context_info {
size_t object_size;
dom_stack_callback_T push[DOM_NODES];
dom_stack_callback_T pop[DOM_NODES];
};
@ -19,6 +20,12 @@ struct dom_stack_context {
/* Data specific to the parser and renderer. */
void *data;
/* This is one big array of context specific objects. */
/* For the SGML parser this holds DTD-oriented info about the node
* (recorded in struct sgml_node_info). E.g. whether an element node
* is optional. */
unsigned char *state_objects;
/* Info about node callbacks and such. */
struct dom_stack_context_info *info;
};
@ -54,13 +61,6 @@ struct dom_stack {
/* Keep nodes when popping them or call done_dom_node() on them. */
unsigned int keep_nodes:1;
/* This is one big array of parser specific objects. */
/* The objects hold parser specific data. For the SGML parser this
* holds DTD-oriented info about the node (recorded in struct
* sgml_node_info). E.g. whether an element node is optional. */
unsigned char *state_objects;
size_t object_size;
/* Callbacks which should be called for the pushed and popped nodes. */
struct dom_stack_context *contexts;
size_t contexts_size;
@ -81,8 +81,8 @@ get_dom_stack_state(struct dom_stack *stack, int top_offset)
#define get_dom_stack_parent(stack) get_dom_stack_state(stack, 1)
#define get_dom_stack_top(stack) get_dom_stack_state(stack, 0)
#define get_dom_stack_state_data(stack, state) \
((void *) &(stack)->state_objects[(state)->depth * (stack)->object_size])
#define get_dom_stack_state_data(context, state) \
((void *) &(context)->state_objects[(state)->depth * (context)->info->object_size])
/* The state iterators do not include the bottom state */

View File

@ -28,7 +28,7 @@
#define get_sgml_parser(stack) ((stack)->contexts->data)
#define get_sgml_parser_state(stack, state) \
get_dom_stack_state_data(stack, state)
get_dom_stack_state_data(stack->contexts, state)
/* Functions for adding new nodes to the DOM tree */
@ -313,6 +313,7 @@ parse_sgml_document(struct dom_stack *stack, struct scanner *scanner)
static struct dom_stack_context_info sgml_parser_context_info = {
/* Object size: */ sizeof(struct sgml_parser_state),
/* Push: */
{
/* */ NULL,
@ -351,7 +352,6 @@ struct sgml_parser *
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
struct uri *uri)
{
size_t obj_size = sizeof(struct sgml_parser_state);
struct sgml_parser *parser;
parser = mem_calloc(1, sizeof(*parser));
@ -361,7 +361,7 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
parser->uri = get_uri_reference(uri);
parser->info = get_sgml_info(doctype);
init_dom_stack(&parser->stack, obj_size,
init_dom_stack(&parser->stack, 0,
type != SGML_PARSER_STREAM);
/* FIXME: Some sgml backend specific callbacks? Handle HTML script tags,
* and feed document.write() data back to the parser. */