1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

DOM: Allocate all node strings when doing incremental rendering

This changes init_dom_node_() to take an allocated argument saying whether
to allocate or not. If the value is -1, node->allocated will be set to the
value of node->parent->allocated. This way the value is inherited like we
do it in the menu code. It should be a sane default since we eventually
want not to rely on the 'underlying' source of the document and there will
be less variables to pass around.
This commit is contained in:
Jonas Fonseca 2006-01-28 04:48:12 +01:00 committed by Jonas Fonseca
parent 24a9d103b4
commit b6b6d3c67e
3 changed files with 60 additions and 31 deletions

View File

@ -314,7 +314,7 @@ get_dom_node_child(struct dom_node *parent, enum dom_node_type type,
struct dom_node *
init_dom_node_(unsigned char *file, int line,
struct dom_node *parent, enum dom_node_type type,
struct dom_string *string)
struct dom_string *string, int allocated)
{
#ifdef DEBUG_MEMLEAK
struct dom_node *node = debug_mem_calloc(file, line, 1, sizeof(*node));
@ -326,7 +326,6 @@ init_dom_node_(unsigned char *file, int line,
node->type = type;
node->parent = parent;
copy_dom_string(&node->string, string);
if (parent) {
struct dom_node_list **list = get_dom_node_list(parent, node);
@ -343,6 +342,22 @@ init_dom_node_(unsigned char *file, int line,
done_dom_node(node);
return NULL;
}
/* Make it possible to add a node to a parent without
* allocating the strings. */
node->allocated = allocated < 0 ? parent->allocated : !!allocated;
} else if (allocated >= 0) {
node->allocated = !!allocated;
}
if (node->allocated) {
if (!init_dom_string(&node->string, string->string, string->length)) {
done_dom_node(node);
return NULL;
}
} else {
copy_dom_string(&node->string, string);
}
return node;
@ -359,10 +374,8 @@ done_dom_node_data(struct dom_node *node)
switch (node->type) {
case DOM_NODE_ATTRIBUTE:
if (node->allocated) {
done_dom_string(&node->string);
if (node->allocated)
done_dom_string(&data->attribute.value);
}
break;
case DOM_NODE_DOCUMENT:
@ -382,31 +395,21 @@ done_dom_node_data(struct dom_node *node)
if (data->element.map)
done_dom_node_list(data->element.map);
if (node->allocated)
done_dom_string(&node->string);
break;
case DOM_NODE_TEXT:
case DOM_NODE_CDATA_SECTION:
case DOM_NODE_ENTITY_REFERENCE:
if (node->allocated)
done_dom_string(&node->string);
break;
case DOM_NODE_PROCESSING_INSTRUCTION:
if (data->proc_instruction.map)
done_dom_node_list(data->proc_instruction.map);
if (node->allocated) {
done_dom_string(&node->string);
if (node->allocated)
done_dom_string(&data->proc_instruction.instruction);
}
break;
default:
break;
}
if (node->allocated)
done_dom_string(&node->string);
mem_free(node);
}

View File

@ -256,12 +256,21 @@ get_dom_node_map_entry(struct dom_node_list *node_map,
enum dom_node_type type, uint16_t subtype,
struct dom_string *name);
/* Removes the node and all its children and free()s itself */
void done_dom_node(struct dom_node *node);
/* The allocated argument is used as the value of node->allocated if >= 0.
* Use -1 to default node->allocated to the value of parent->allocated. */
struct dom_node *
init_dom_node_(unsigned char *file, int line,
struct dom_node *parent, enum dom_node_type type,
struct dom_string *string);
#define init_dom_node(type, string) init_dom_node_(__FILE__, __LINE__, NULL, type, string)
#define add_dom_node(parent, type, string) init_dom_node_(__FILE__, __LINE__, parent, type, string)
struct dom_string *string, int allocated);
#define init_dom_node(type, string, allocated) \
init_dom_node_(__FILE__, __LINE__, NULL, type, string, allocated)
#define add_dom_node(parent, type, string) \
init_dom_node_(__FILE__, __LINE__, parent, type, string, -1)
#define add_dom_element(parent, string) \
add_dom_node(parent, DOM_NODE_ELEMENT, string)
@ -273,7 +282,16 @@ add_dom_attribute(struct dom_node *parent, struct dom_string *name,
struct dom_node *node = add_dom_node(parent, DOM_NODE_ATTRIBUTE, name);
if (node && value) {
copy_dom_string(&node->data.attribute.value, value);
struct dom_string *str = &node->data.attribute.value;
if (node->allocated) {
if (!init_dom_string(str, value->string, value->length)) {
done_dom_node(node);
return NULL;
}
} else {
copy_dom_string(str, value);
}
}
return node;
@ -286,15 +304,21 @@ add_dom_proc_instruction(struct dom_node *parent, struct dom_string *string,
struct dom_node *node = add_dom_node(parent, DOM_NODE_PROCESSING_INSTRUCTION, string);
if (node && instruction) {
copy_dom_string(&node->data.proc_instruction.instruction, instruction);
struct dom_string *str = &node->data.proc_instruction.instruction;
if (node->allocated) {
if (!init_dom_string(str, instruction->string, instruction->length)) {
done_dom_node(node);
return NULL;
}
} else {
copy_dom_string(str, instruction);
}
}
return node;
}
/* Removes the node and all its children and free()s itself */
void done_dom_node(struct dom_node *node);
/* Compare two nodes returning non-zero if they differ. */
int dom_node_casecmp(struct dom_node *node1, struct dom_node *node2);

View File

@ -35,11 +35,13 @@
* information like node subtypes and SGML parser state information. */
static inline struct dom_node *
add_sgml_document(struct dom_stack *stack, struct dom_string *string)
add_sgml_document(struct sgml_parser *parser)
{
struct dom_node *node = init_dom_node(DOM_NODE_DOCUMENT, string);
int allocated = parser->flags & SGML_PARSER_INCREMENTAL;
struct dom_node *node;
if (node && push_dom_node(stack, node) == DOM_STACK_CODE_OK)
node = init_dom_node(DOM_NODE_DOCUMENT, &parser->uri, allocated);
if (node && push_dom_node(&parser->stack, node) == DOM_STACK_CODE_OK)
return node;
return NULL;
@ -432,13 +434,13 @@ parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
parser->flags |= SGML_PARSER_COMPLETE;
if (!parser->root) {
parser->root = add_sgml_document(&parser->stack, &parser->uri);
parser->root = add_sgml_document(parser);
if (!parser->root)
return SGML_PARSER_CODE_MEM_ALLOC;
get_dom_stack_top(&parser->stack)->immutable = 1;
}
node = init_dom_node(DOM_NODE_TEXT, &source);
node = init_dom_node(DOM_NODE_TEXT, &source, 0);
if (!node || push_dom_node(&parser->parsing, node) != DOM_STACK_CODE_OK)
return SGML_PARSER_CODE_MEM_ALLOC;