summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tokeniser/tokeniser.c2
-rw-r--r--src/treebuilder/internal.h12
-rw-r--r--src/treebuilder/treebuilder.c71
3 files changed, 83 insertions, 2 deletions
diff --git a/src/tokeniser/tokeniser.c b/src/tokeniser/tokeniser.c
index 66c36d5..a44de07 100644
--- a/src/tokeniser/tokeniser.c
+++ b/src/tokeniser/tokeniser.c
@@ -3263,7 +3263,7 @@ hubbub_error hubbub_tokeniser_handle_cdata_block(hubbub_tokeniser *tokeniser)
c = *cptr;
- if (c == ']' && (tokeniser->context.match_cdata.end >= 0)) {
+ if (c == ']') {
tokeniser->context.pending += len;
tokeniser->context.match_cdata.end += len;
} else if (c == '>' && tokeniser->context.match_cdata.end >= 2) {
diff --git a/src/treebuilder/internal.h b/src/treebuilder/internal.h
index 5d3c75f..de371b0 100644
--- a/src/treebuilder/internal.h
+++ b/src/treebuilder/internal.h
@@ -57,6 +57,7 @@ typedef struct element_context
* instead of the current node." */
void *node; /**< Node pointer */
+
hubbub_attribute *attributes; /**< The attributes associated with
* element*/
size_t n_attributes; /**< Number of attributes associated
@@ -84,6 +85,11 @@ typedef struct hubbub_treebuilder_context
insertion_mode mode; /**< The current insertion mode */
insertion_mode second_mode; /**< The secondary insertion mode */
+#define TEMPLATE_STACK_CHUNK 32
+ insertion_mode *template_stack; /**< The stack of Template insertion modes*/
+ int32_t current_template_mode; /**< The index of template_stack's top element*/
+ uint32_t template_stack_alloc; /**< Number of stack slots allocated */
+
#define ELEMENT_STACK_CHUNK 128
element_context *element_stack; /**< Stack of open elements */
uint32_t stack_alloc; /**< Number of stack slots allocated */
@@ -178,6 +184,12 @@ hubbub_error element_stack_push(hubbub_treebuilder *treebuilder,
hubbub_attribute *attrs, size_t n_attrs);
hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder,
hubbub_ns *ns, element_type *type, void **node);
+
+hubbub_error template_stack_push(hubbub_treebuilder *treebuilder,
+ insertion_mode mode);
+hubbub_error template_stack_pop(hubbub_treebuilder *treebuilder,
+ insertion_mode *mode);
+
hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder,
element_type type);
hubbub_error element_stack_remove(hubbub_treebuilder *treebuilder,
diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c
index eb6bb51..8f0e7e3 100644
--- a/src/treebuilder/treebuilder.c
+++ b/src/treebuilder/treebuilder.c
@@ -138,6 +138,16 @@ hubbub_error hubbub_treebuilder_create(hubbub_tokeniser *tokeniser,
free(tb);
return HUBBUB_NOMEM;
}
+
+ tb->context.template_stack = malloc(
+ TEMPLATE_STACK_CHUNK * sizeof(insertion_mode));
+ if (tb->context.template_stack == NULL) {
+ free(tb);
+ return HUBBUB_NOMEM;
+ }
+ tb->context.template_stack_alloc = TEMPLATE_STACK_CHUNK;
+ tb->context.current_template_mode = -1;
+
tb->context.stack_alloc = ELEMENT_STACK_CHUNK;
/* We rely on HTML not being equal to zero to determine
* if the first item in the stack is in use. Assert this here. */
@@ -160,6 +170,7 @@ hubbub_error hubbub_treebuilder_create(hubbub_tokeniser *tokeniser,
HUBBUB_TOKENISER_TOKEN_HANDLER, &tokparams);
if (error != HUBBUB_OK) {
free(tb->context.element_stack);
+ free(tb->context.template_stack);
free(tb);
return error;
}
@@ -216,16 +227,21 @@ hubbub_error hubbub_treebuilder_destroy(hubbub_treebuilder *treebuilder)
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[n].node);
+
}
if (treebuilder->context.element_stack[0].type == HTML) {
treebuilder->tree_handler->unref_node(
treebuilder->tree_handler->ctx,
treebuilder->context.element_stack[0].node);
}
+ /*\todo free attributes?*/
}
free(treebuilder->context.element_stack);
treebuilder->context.element_stack = NULL;
+ free(treebuilder->context.template_stack);
+ treebuilder->context.template_stack = NULL;
+
for (entry = treebuilder->context.formatting_list; entry != NULL;
entry = next) {
next = entry->next;
@@ -235,7 +251,7 @@ hubbub_error hubbub_treebuilder_destroy(hubbub_treebuilder *treebuilder)
treebuilder->tree_handler->ctx,
entry->details.node);
}
-
+ /*\todo free attributes? */
free(entry);
}
@@ -1291,6 +1307,59 @@ hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder,
}
/**
+ * Push an element onto the stack of Template Insertion Modes
+ *
+ * \param treebuilder The treebuilder instance containing the stack
+ * \param mode The insertion mode being pushed
+ * \return HUBBUB_OK on success, appropriate error otherwise.
+ */
+hubbub_error template_stack_push(hubbub_treebuilder *treebuilder,
+ insertion_mode mode)
+{
+ int32_t slot = treebuilder->context.current_template_mode + 1;
+
+ if (slot >= (signed)treebuilder->context.template_stack_alloc) {
+ insertion_mode *temp = realloc(
+ treebuilder->context.template_stack,
+ (treebuilder->context.template_stack_alloc +
+ TEMPLATE_STACK_CHUNK) *
+ sizeof(insertion_mode));
+
+ if (temp == NULL)
+ return HUBBUB_NOMEM;
+
+ treebuilder->context.template_stack = temp;
+ treebuilder->context.template_stack_alloc += TEMPLATE_STACK_CHUNK;
+ }
+
+ treebuilder->context.template_stack[slot] = mode;
+
+ treebuilder->context.current_template_mode = slot;
+
+ return HUBBUB_OK;
+}
+
+/**
+ * Pop an element off the stack of Template Insertion Modes
+ *
+ * \param ns Pointer to location to receive insertion mode
+ * \return HUBBUB_OK on success, appropriate error otherwise.
+ */
+hubbub_error template_stack_pop(hubbub_treebuilder *treebuilder,
+ insertion_mode *mode)
+{
+ int32_t stack =
+ treebuilder->context.current_template_mode;
+ *mode = treebuilder->context.template_stack[stack];
+
+ treebuilder->context.current_template_mode -= 1;
+
+ assert( treebuilder->context.current_template_mode >= -1);
+
+ return HUBBUB_OK;
+}
+
+/**
* Pop elements until an element of type "element" has been popped.
*
* \return HUBBUB_OK on success, appropriate error otherwise.