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

Make it easier to work with DOM stack contexts outside of the callbacks

The problem is to get access to the context when it is not the first one
and it has to happen outside of the context callbacks. This changes the
memory management so that the context adder returns the context. To further
improve the use of contexts add a context destructor which makes it
possible to unregister (temporary) contexts.
This commit is contained in:
Jonas Fonseca 2005-12-27 05:59:12 +01:00 committed by Jonas Fonseca
parent 774aa70c6f
commit a4831fef2d
5 changed files with 54 additions and 17 deletions

View File

@ -505,7 +505,7 @@ render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, vo
{
struct dom_renderer *renderer = stack->current->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 sgml_parser_state *pstate = get_dom_stack_state_data(stack->contexts[0], state);
struct scanner_token *token = &pstate->end_token;
unsigned char *string = token->string;
int length = token->length;

View File

@ -770,7 +770,7 @@ match_attribute_selectors(struct dom_select_node *base, struct dom_node *node)
/* XXX: Assume the first context is the one! */
#define get_dom_select_state(stack, state) \
((struct dom_select_state *) get_dom_stack_state_data((stack)->contexts, state))
((struct dom_select_state *) get_dom_stack_state_data((stack)->contexts[0], state))
static int
match_element_relation(struct dom_select_node *selector, struct dom_node *node,

View File

@ -29,10 +29,10 @@ realloc_dom_stack_states(struct dom_stack_state **states, size_t size)
}
static inline struct dom_stack_state *
realloc_dom_stack_context(struct dom_stack_context **contexts, size_t size)
realloc_dom_stack_context(struct dom_stack_context ***contexts, size_t size)
{
return mem_align_alloc(contexts, size, size + 1,
struct dom_stack_context,
struct dom_stack_context *,
DOM_STACK_STATE_GRANULARITY);
}
@ -70,7 +70,8 @@ done_dom_stack(struct dom_stack *stack)
assert(stack);
for (i = 0; i < stack->contexts_size; i++) {
mem_free_if(stack->contexts[i].state_objects);
mem_free_if(stack->contexts[i]->state_objects);
mem_free(stack->contexts[i]);
}
mem_free_if(stack->contexts);
@ -79,18 +80,48 @@ done_dom_stack(struct dom_stack *stack)
memset(stack, 0, sizeof(*stack));
}
void
struct dom_stack_context *
add_dom_stack_context(struct dom_stack *stack, void *data,
struct dom_stack_context_info *context_info)
{
struct dom_stack_context *context;
if (!realloc_dom_stack_context(&stack->contexts, stack->contexts_size))
return;
return NULL;
context = &stack->contexts[stack->contexts_size++];
context = mem_calloc(1, sizeof(*context));
if (!context)
return NULL;
stack->contexts[stack->contexts_size++] = context;
context->info = context_info;
context->data = data;
return context;
}
void
done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *context)
{
size_t i;
mem_free_if(context->state_objects);
mem_free(context);
/* Handle the trivial case of temporary contexts optimally by iteration last added first. */
for (i = stack->contexts_size - 1; i >= 0; i--) {
if (stack->contexts[i] != context)
continue;
stack->contexts_size--;
if (i < stack->contexts_size) {
struct dom_stack_context **pos = &stack->contexts[i];
size_t size = stack->contexts_size - i;
memmove(pos, pos + 1, size * sizeof(*pos));
}
break;
}
}
enum dom_stack_action {
@ -105,7 +136,7 @@ call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
int i;
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
struct dom_stack_context *context = stack->contexts[i];
void *state_data = get_dom_stack_state_data(context, state);
dom_stack_callback_T callback;
@ -144,7 +175,7 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
state += stack->depth;
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
struct dom_stack_context *context = stack->contexts[i];
if (context->info->object_size
&& !realloc_dom_stack_state_objects(context, stack->depth)) {
@ -188,7 +219,7 @@ pop_dom_node(struct dom_stack *stack)
assert(stack->depth >= 0);
for (i = 0; i < stack->contexts_size; i++) {
struct dom_stack_context *context = &stack->contexts[i];
struct dom_stack_context *context = stack->contexts[i];
if (context->info->object_size) {
void *state_data = get_dom_stack_state_data(context, state);

View File

@ -70,7 +70,7 @@ struct dom_stack {
enum dom_stack_flag flags;
/* Contexts for the pushed and popped nodes. */
struct dom_stack_context *contexts;
struct dom_stack_context **contexts;
size_t contexts_size;
/* The current context. */
@ -136,8 +136,14 @@ void done_dom_stack(struct dom_stack *stack);
/* Add a context to the stack. This is needed if either you want to have the
* stack allocated objects for created states and/or if you want to install
* callbacks for pushing or popping. . */
void add_dom_stack_context(struct dom_stack *stack, void *data,
struct dom_stack_context_info *context_info);
struct dom_stack_context *
add_dom_stack_context(struct dom_stack *stack, void *data,
struct dom_stack_context_info *context_info);
/* Unregister a stack @context. This should be done especially for temporary
* stack contexts (without any callbacks) so that they do not increasing the
* memory usage. */
void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *context);
/* Decends down to the given node making it the current parent */
/* If an error occurs the node is free()d and NULL is returned */

View File

@ -29,10 +29,10 @@ init_sgml_parsing_state(struct sgml_parser *parser, struct string *buffer);
* is the first to add it's context, which it is since it initializes the
* stack. */
#define get_sgml_parser(stack) ((stack)->contexts->data)
#define get_sgml_parser(stack) ((stack)->contexts[0]->data)
#define get_sgml_parser_state(stack, state) \
get_dom_stack_state_data(stack->contexts, state)
get_dom_stack_state_data(stack->contexts[0], state)
/* Functions for adding new nodes to the DOM tree: */
@ -432,7 +432,7 @@ init_sgml_parsing_state(struct sgml_parser *parser, struct string *buffer)
state = get_dom_stack_top(&parser->parsing);
return get_dom_stack_state_data(parser->parsing.contexts, state);
return get_dom_stack_state_data(parser->parsing.contexts[0], state);
}