From c0665aa47779e3e19d3cb7b03c2763990ae5edb6 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 9 Aug 2020 20:05:30 +0300 Subject: [PATCH] HTML: added clone/deep clone functions for nodes. This related https://github.com/rushter/selectolax/issues/27 issue on GitHub. --- source/myhtml/myhtml.c | 76 ++++++++++++++++++++++++++++++++++++++++++ source/myhtml/myhtml.h | 3 ++ 2 files changed, 79 insertions(+) diff --git a/source/myhtml/myhtml.c b/source/myhtml/myhtml.c index 81b377e..550c285 100644 --- a/source/myhtml/myhtml.c +++ b/source/myhtml/myhtml.c @@ -1636,6 +1636,82 @@ myhtml_version_t myhtml_version(void) return (myhtml_version_t){MyHTML_VERSION_MAJOR, MyHTML_VERSION_MINOR, MyHTML_VERSION_PATCH}; } +myhtml_tree_node_t * myhtml_node_clone(myhtml_tree_t* dest_tree, myhtml_tree_node_t* src) +{ + myhtml_tag_id_t tag_id; + const myhtml_tag_context_t* tag_to, * tag_from; + myhtml_tree_node_t* new_node = myhtml_tree_node_create(dest_tree); + tag_id = src->tag_id; + if (tag_id >= MyHTML_TAG_LAST_ENTRY) { + tag_to = myhtml_tag_get_by_id(dest_tree->tags, src->tag_id); + tag_from = myhtml_tag_get_by_id(src->tree->tags, src->tag_id); + if (tag_to == NULL + || tag_to->name_length != tag_from->name_length + || mycore_strncmp(tag_to->name, tag_from->name, tag_from->name_length) != 0) + { + tag_id = myhtml_tag_add(dest_tree->tags, tag_from->name, tag_from->name_length, + MyHTML_TOKENIZER_STATE_DATA, true); + } + } + + new_node->token = myhtml_token_node_clone(dest_tree->token, src->token, + dest_tree->mcasync_rules_token_id, + dest_tree->mcasync_rules_attr_id); + new_node->tag_id = tag_id; + new_node->ns = src->ns; + + if(new_node->token) { + new_node->token->tag_id = tag_id; + new_node->token->type |= MyHTML_TOKEN_TYPE_DONE; + } + + return new_node; +} + +myhtml_tree_node_t * myhtml_node_clone_deep(myhtml_tree_t* dest_tree, myhtml_tree_node_t* src) +{ + myhtml_tree_node_t* cloned, *root, *node; + myhtml_tree_node_t* scope_node = src; + + if(scope_node && scope_node->tree && scope_node->tree->document == scope_node) { + src = scope_node->child; + } + + root = node = myhtml_node_clone(dest_tree, src); + if (root == NULL) { + return NULL; + } + + src = src->child; + + while(src != NULL) { + cloned = myhtml_node_clone(dest_tree, src); + if (cloned == NULL) { + return NULL; + } + + myhtml_tree_node_add_child(node, cloned); + + if(src->child) { + src = src->child; + node = cloned; + } + else { + while(src != scope_node && src->next == NULL) { + node = node->parent; + src = src->parent; + } + + if(src == scope_node) { + break; + } + + src = src->next; + } + } + + return root; +} diff --git a/source/myhtml/myhtml.h b/source/myhtml/myhtml.h index e7208cc..4cca62c 100644 --- a/source/myhtml/myhtml.h +++ b/source/myhtml/myhtml.h @@ -161,6 +161,8 @@ myhtml_tree_node_t * myhtml_node_insert_after(myhtml_tree_node_t *target, myhtml myhtml_tree_node_t * myhtml_node_insert_before(myhtml_tree_node_t *target, myhtml_tree_node_t *node); myhtml_tree_node_t * myhtml_node_create(myhtml_tree_t* tree, myhtml_tag_id_t tag_id, enum myhtml_namespace ns); +myhtml_tree_node_t * myhtml_node_clone(myhtml_tree_t* dest_tree, myhtml_tree_node_t* src); +myhtml_tree_node_t * myhtml_node_clone_deep(myhtml_tree_t* dest_tree, myhtml_tree_node_t* src); myhtml_tree_node_t * myhtml_node_remove(myhtml_tree_node_t *node); void myhtml_node_delete(myhtml_tree_node_t *node); void myhtml_node_delete_recursive(myhtml_tree_node_t *node); @@ -221,6 +223,7 @@ mystatus_t myhtml_queue_add(myhtml_tree_t *tree, size_t begin, myhtml_token_node /* version */ myhtml_version_t myhtml_version(void); + #ifdef __cplusplus } /* extern "C" */ #endif