mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Move the state_objects to the DOM stack contexts
This way all contexts are now separated, almost.
This commit is contained in:
parent
910c51abaf
commit
f8d48e81eb
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user