xref: /php-src/ext/dom/lexbor/lexbor/html/interface.c (revision bffab33a)
1 /*
2  * Copyright (C) 2018-2021 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #include "lexbor/core/mraw.h"
8 
9 #include "lexbor/html/interface.h"
10 #include "lexbor/html/interfaces/document.h"
11 
12 #include "lexbor/dom/interface.h"
13 
14 #define LXB_HTML_INTERFACE_RES_CONSTRUCTORS
15 #define LXB_HTML_INTERFACE_RES_DESTRUCTOR
16 #include "lexbor/html/interface_res.h"
17 
18 
19 static lxb_dom_element_t *
20 lxb_html_interface_clone_element(lxb_dom_document_t *document,
21                                  const lxb_dom_element_t *element);
22 
23 
24 lxb_dom_interface_t *
lxb_html_interface_create(lxb_html_document_t * document,lxb_tag_id_t tag_id,lxb_ns_id_t ns)25 lxb_html_interface_create(lxb_html_document_t *document, lxb_tag_id_t tag_id,
26                           lxb_ns_id_t ns)
27 {
28     lxb_dom_node_t *node;
29 
30     if (tag_id >= LXB_TAG__LAST_ENTRY) {
31         if (ns == LXB_NS_HTML) {
32             lxb_html_unknown_element_t *unel;
33 
34             unel = lxb_html_unknown_element_interface_create(document);
35             node = lxb_dom_interface_node(unel);
36         }
37         else if (ns == LXB_NS_SVG) {
38             /* TODO: For this need implement SVGElement */
39             lxb_dom_element_t *domel;
40 
41             domel = lxb_dom_element_interface_create(&document->dom_document);
42             node = lxb_dom_interface_node(domel);
43         }
44         else {
45             lxb_dom_element_t *domel;
46 
47             domel = lxb_dom_element_interface_create(&document->dom_document);
48             node = lxb_dom_interface_node(domel);
49         }
50     }
51     else {
52         node = lxb_html_interface_res_constructors[tag_id][ns](document);
53     }
54 
55     if (node == NULL) {
56         return NULL;
57     }
58 
59     node->local_name = tag_id;
60     node->ns = ns;
61 
62     return node;
63 }
64 
65 lxb_dom_interface_t *
lxb_html_interface_clone(lxb_dom_document_t * document,const lxb_dom_interface_t * intrfc)66 lxb_html_interface_clone(lxb_dom_document_t *document,
67                          const lxb_dom_interface_t *intrfc)
68 {
69     const lxb_dom_node_t *node = intrfc;
70 
71     if (document == NULL) {
72         document = node->owner_document;
73     }
74 
75     switch (node->type) {
76         case LXB_DOM_NODE_TYPE_ELEMENT:
77             return lxb_html_interface_clone_element(document, intrfc);
78 
79         case LXB_DOM_NODE_TYPE_TEXT:
80             return lxb_dom_text_interface_clone(document, intrfc);
81 
82         case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
83             return lxb_dom_processing_instruction_interface_clone(document,
84                                                                   intrfc);
85         case LXB_DOM_NODE_TYPE_COMMENT:
86             return lxb_dom_comment_interface_clone(document, intrfc);
87 
88         case LXB_DOM_NODE_TYPE_DOCUMENT:
89             return lxb_dom_document_interface_clone(document, intrfc);
90 
91         case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
92             return lxb_dom_document_type_interface_clone(document, intrfc);
93 
94         default:
95             return lxb_dom_node_interface_clone(document, node, false);
96     }
97 }
98 
99 static lxb_dom_element_t *
lxb_html_interface_clone_element(lxb_dom_document_t * document,const lxb_dom_element_t * element)100 lxb_html_interface_clone_element(lxb_dom_document_t *document,
101                                  const lxb_dom_element_t *element)
102 {
103     lxb_dom_element_t *new;
104     const lxb_dom_node_t *node = lxb_dom_interface_node(element);
105 
106     new = lxb_html_interface_create((lxb_html_document_t *) document,
107                                     node->local_name, node->ns);
108     if (new == NULL) {
109         return NULL;
110     }
111 
112     if (lxb_dom_element_interface_copy(new, element) != LXB_STATUS_OK) {
113         return lxb_dom_element_interface_destroy(new);
114     }
115 
116     return new;
117 }
118 
119 lxb_dom_interface_t *
lxb_html_interface_destroy(lxb_dom_interface_t * intrfc)120 lxb_html_interface_destroy(lxb_dom_interface_t *intrfc)
121 {
122     if (intrfc == NULL) {
123         return NULL;
124     }
125 
126     lxb_dom_node_t *node = intrfc;
127 
128     switch (node->type) {
129         case LXB_DOM_NODE_TYPE_TEXT:
130         case LXB_DOM_NODE_TYPE_COMMENT:
131         case LXB_DOM_NODE_TYPE_ELEMENT:
132         case LXB_DOM_NODE_TYPE_DOCUMENT:
133         case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
134             if (node->local_name >= LXB_TAG__LAST_ENTRY) {
135                 if (node->ns == LXB_NS_HTML) {
136                     return lxb_html_unknown_element_interface_destroy(intrfc);
137                 }
138                 else if (node->ns == LXB_NS_SVG) {
139                     /* TODO: For this need implement SVGElement */
140                     return lxb_dom_element_interface_destroy(intrfc);
141                 }
142                 else {
143                     return lxb_dom_element_interface_destroy(intrfc);
144                 }
145             }
146             else {
147                 return lxb_html_interface_res_destructor[node->local_name][node->ns](intrfc);
148             }
149 
150         case LXB_DOM_NODE_TYPE_ATTRIBUTE:
151             return lxb_dom_attr_interface_destroy(intrfc);
152 
153         case LXB_DOM_NODE_TYPE_CDATA_SECTION:
154             return lxb_dom_cdata_section_interface_destroy(intrfc);
155 
156         case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
157             return lxb_dom_document_fragment_interface_destroy(intrfc);
158 
159         case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
160             return lxb_dom_processing_instruction_interface_destroy(intrfc);
161 
162         default:
163             return NULL;
164     }
165 }
166