diff options
Diffstat (limited to 'src/treebuilder')
-rw-r--r-- | src/treebuilder/internal.h | 12 | ||||
-rw-r--r-- | src/treebuilder/treebuilder.c | 71 |
2 files changed, 82 insertions, 1 deletions
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. |