1 /*
2 * Copyright (C) 2018 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #include "lexbor/html/tree/open_elements.h"
8 #include "lexbor/html/tree.h"
9
10
11 LXB_API void
lxb_html_tree_open_elements_remove_by_node(lxb_html_tree_t * tree,lxb_dom_node_t * node)12 lxb_html_tree_open_elements_remove_by_node(lxb_html_tree_t *tree,
13 lxb_dom_node_t *node)
14 {
15 size_t delta;
16 void **list = tree->open_elements->list;
17 size_t len = tree->open_elements->length;
18
19 while (len != 0) {
20 len--;
21
22 if (list[len] == node) {
23 delta = tree->open_elements->length - len - 1;
24
25 memmove(list + len, list + len + 1, sizeof(void *) * delta);
26
27 tree->open_elements->length--;
28
29 break;
30 }
31 }
32 }
33
34 void
lxb_html_tree_open_elements_pop_until_tag_id(lxb_html_tree_t * tree,lxb_tag_id_t tag_id,lxb_ns_id_t ns,bool exclude)35 lxb_html_tree_open_elements_pop_until_tag_id(lxb_html_tree_t *tree,
36 lxb_tag_id_t tag_id,
37 lxb_ns_id_t ns,
38 bool exclude)
39 {
40 void **list = tree->open_elements->list;
41 lxb_dom_node_t *node;
42
43 while (tree->open_elements->length != 0) {
44 tree->open_elements->length--;
45
46 node = list[ tree->open_elements->length ];
47
48 if (node->local_name == tag_id && node->ns == ns) {
49 if (exclude == false) {
50 tree->open_elements->length++;
51 }
52
53 break;
54 }
55 }
56 }
57
58 void
lxb_html_tree_open_elements_pop_until_h123456(lxb_html_tree_t * tree)59 lxb_html_tree_open_elements_pop_until_h123456(lxb_html_tree_t *tree)
60 {
61 void **list = tree->open_elements->list;
62 lxb_dom_node_t *node;
63
64 while (tree->open_elements->length != 0) {
65 tree->open_elements->length--;
66
67 node = list[ tree->open_elements->length ];
68
69 switch (node->local_name) {
70 case LXB_TAG_H1:
71 case LXB_TAG_H2:
72 case LXB_TAG_H3:
73 case LXB_TAG_H4:
74 case LXB_TAG_H5:
75 case LXB_TAG_H6:
76 if (node->ns == LXB_NS_HTML) {
77 return;
78 }
79
80 break;
81
82 default:
83 break;
84 }
85 }
86 }
87
88 void
lxb_html_tree_open_elements_pop_until_td_th(lxb_html_tree_t * tree)89 lxb_html_tree_open_elements_pop_until_td_th(lxb_html_tree_t *tree)
90 {
91 void **list = tree->open_elements->list;
92 lxb_dom_node_t *node;
93
94 while (tree->open_elements->length != 0) {
95 tree->open_elements->length--;
96
97 node = list[ tree->open_elements->length ];
98
99 switch (node->local_name) {
100 case LXB_TAG_TD:
101 case LXB_TAG_TH:
102 if (node->ns == LXB_NS_HTML) {
103 return;
104 }
105
106 break;
107
108 default:
109 break;
110 }
111 }
112 }
113
114 void
lxb_html_tree_open_elements_pop_until_node(lxb_html_tree_t * tree,lxb_dom_node_t * node,bool exclude)115 lxb_html_tree_open_elements_pop_until_node(lxb_html_tree_t *tree,
116 lxb_dom_node_t *node,
117 bool exclude)
118 {
119 void **list = tree->open_elements->list;
120
121 while (tree->open_elements->length != 0) {
122 tree->open_elements->length--;
123
124 if (list[ tree->open_elements->length ] == node) {
125 if (exclude == false) {
126 tree->open_elements->length++;
127 }
128
129 break;
130 }
131 }
132 }
133
134 void
lxb_html_tree_open_elements_pop_until(lxb_html_tree_t * tree,size_t idx,bool exclude)135 lxb_html_tree_open_elements_pop_until(lxb_html_tree_t *tree, size_t idx,
136 bool exclude)
137 {
138 tree->open_elements->length = idx;
139
140 if (exclude == false) {
141 tree->open_elements->length++;
142 }
143 }
144
145 bool
lxb_html_tree_open_elements_find_by_node(lxb_html_tree_t * tree,lxb_dom_node_t * node,size_t * return_pos)146 lxb_html_tree_open_elements_find_by_node(lxb_html_tree_t *tree,
147 lxb_dom_node_t *node,
148 size_t *return_pos)
149 {
150 void **list = tree->open_elements->list;
151
152 for (size_t i = 0; i < tree->open_elements->length; i++) {
153 if (list[i] == node) {
154 if (return_pos) {
155 *return_pos = i;
156 }
157
158 return true;
159 }
160 }
161
162 if (return_pos) {
163 *return_pos = 0;
164 }
165
166 return false;
167 }
168
169 bool
lxb_html_tree_open_elements_find_by_node_reverse(lxb_html_tree_t * tree,lxb_dom_node_t * node,size_t * return_pos)170 lxb_html_tree_open_elements_find_by_node_reverse(lxb_html_tree_t *tree,
171 lxb_dom_node_t *node,
172 size_t *return_pos)
173 {
174 void **list = tree->open_elements->list;
175 size_t len = tree->open_elements->length;
176
177 while (len != 0) {
178 len--;
179
180 if (list[len] == node) {
181 if (return_pos) {
182 *return_pos = len;
183 }
184
185 return true;
186 }
187 }
188
189 if (return_pos) {
190 *return_pos = 0;
191 }
192
193 return false;
194 }
195
196 lxb_dom_node_t *
lxb_html_tree_open_elements_find(lxb_html_tree_t * tree,lxb_tag_id_t tag_id,lxb_ns_id_t ns,size_t * return_index)197 lxb_html_tree_open_elements_find(lxb_html_tree_t *tree,
198 lxb_tag_id_t tag_id, lxb_ns_id_t ns,
199 size_t *return_index)
200 {
201 void **list = tree->open_elements->list;
202 lxb_dom_node_t *node;
203
204 for (size_t i = 0; i < tree->open_elements->length; i++) {
205 node = list[i];
206
207 if (node->local_name == tag_id && node->ns == ns) {
208 if (return_index) {
209 *return_index = i;
210 }
211
212 return node;
213 }
214 }
215
216 if (return_index) {
217 *return_index = 0;
218 }
219
220 return NULL;
221 }
222
223 lxb_dom_node_t *
lxb_html_tree_open_elements_find_reverse(lxb_html_tree_t * tree,lxb_tag_id_t tag_id,lxb_ns_id_t ns,size_t * return_index)224 lxb_html_tree_open_elements_find_reverse(lxb_html_tree_t *tree,
225 lxb_tag_id_t tag_id, lxb_ns_id_t ns,
226 size_t *return_index)
227 {
228 void **list = tree->open_elements->list;
229 size_t len = tree->open_elements->length;
230
231 lxb_dom_node_t *node;
232
233 while (len != 0) {
234 len--;
235 node = list[len];
236
237 if (node->local_name == tag_id && node->ns == ns) {
238 if (return_index) {
239 *return_index = len;
240 }
241
242 return node;
243 }
244 }
245
246 if (return_index) {
247 *return_index = 0;
248 }
249
250 return NULL;
251 }
252