1 /*
2 * Copyright (C) 2018-2021 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #ifndef LEXBOR_DOM_ELEMENT_H
8 #define LEXBOR_DOM_ELEMENT_H
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 #include "lexbor/core/str.h"
15
16 #include "lexbor/dom/interfaces/document.h"
17 #include "lexbor/dom/interfaces/node.h"
18 #include "lexbor/dom/collection.h"
19 #include "lexbor/dom/interfaces/attr.h"
20
21 #include "lexbor/tag/tag.h"
22
23
24 typedef enum {
25 LXB_DOM_ELEMENT_CUSTOM_STATE_UNDEFINED = 0x00,
26 LXB_DOM_ELEMENT_CUSTOM_STATE_FAILED = 0x01,
27 LXB_DOM_ELEMENT_CUSTOM_STATE_UNCUSTOMIZED = 0x02,
28 LXB_DOM_ELEMENT_CUSTOM_STATE_CUSTOM = 0x03
29 }
30 lxb_dom_element_custom_state_t;
31
32 struct lxb_dom_element {
33 lxb_dom_node_t node;
34
35 /* For example: <LalAla:DiV Fix:Me="value"> */
36
37 /* uppercase, with prefix: LALALA:DIV */
38 lxb_dom_attr_id_t upper_name;
39
40 /* original, with prefix: LalAla:DiV */
41 lxb_dom_attr_id_t qualified_name;
42
43 lexbor_str_t *is_value;
44
45 lxb_dom_attr_t *first_attr;
46 lxb_dom_attr_t *last_attr;
47
48 lxb_dom_attr_t *attr_id;
49 lxb_dom_attr_t *attr_class;
50
51 lxb_dom_element_custom_state_t custom_state;
52 };
53
54
55 LXB_API lxb_dom_element_t *
56 lxb_dom_element_interface_create(lxb_dom_document_t *document);
57
58 LXB_API lxb_dom_element_t *
59 lxb_dom_element_interface_clone(lxb_dom_document_t *document,
60 const lxb_dom_element_t *element);
61
62 LXB_API lxb_dom_element_t *
63 lxb_dom_element_interface_destroy(lxb_dom_element_t *element);
64
65 LXB_API lxb_status_t
66 lxb_dom_element_interface_copy(lxb_dom_element_t *dst,
67 const lxb_dom_element_t *src);
68
69 LXB_API lxb_dom_element_t *
70 lxb_dom_element_create(lxb_dom_document_t *document,
71 const lxb_char_t *local_name, size_t lname_len,
72 const lxb_char_t *ns_name, size_t ns_len,
73 const lxb_char_t *prefix, size_t prefix_len,
74 const lxb_char_t *is, size_t is_len,
75 bool sync_custom);
76
77 LXB_API lxb_dom_element_t *
78 lxb_dom_element_destroy(lxb_dom_element_t *element);
79
80 LXB_API bool
81 lxb_dom_element_has_attributes(lxb_dom_element_t *element);
82
83 LXB_API lxb_dom_attr_t *
84 lxb_dom_element_set_attribute(lxb_dom_element_t *element,
85 const lxb_char_t *qualified_name, size_t qn_len,
86 const lxb_char_t *value, size_t value_len);
87
88 LXB_API const lxb_char_t *
89 lxb_dom_element_get_attribute(lxb_dom_element_t *element,
90 const lxb_char_t *qualified_name, size_t qn_len,
91 size_t *value_len);
92
93 LXB_API lxb_status_t
94 lxb_dom_element_remove_attribute(lxb_dom_element_t *element,
95 const lxb_char_t *qualified_name, size_t qn_len);
96
97 LXB_API bool
98 lxb_dom_element_has_attribute(lxb_dom_element_t *element,
99 const lxb_char_t *qualified_name, size_t qn_len);
100
101 LXB_API lxb_status_t
102 lxb_dom_element_attr_append(lxb_dom_element_t *element, lxb_dom_attr_t *attr);
103
104 LXB_API lxb_status_t
105 lxb_dom_element_attr_remove(lxb_dom_element_t *element, lxb_dom_attr_t *attr);
106
107 LXB_API lxb_dom_attr_t *
108 lxb_dom_element_attr_by_name(lxb_dom_element_t *element,
109 const lxb_char_t *qualified_name, size_t length);
110
111 LXB_API lxb_dom_attr_t *
112 lxb_dom_element_attr_by_local_name_data(lxb_dom_element_t *element,
113 const lxb_dom_attr_data_t *data);
114
115 LXB_API lxb_dom_attr_t *
116 lxb_dom_element_attr_by_id(lxb_dom_element_t *element,
117 lxb_dom_attr_id_t attr_id);
118
119 LXB_API lxb_dom_attr_t *
120 lxb_dom_element_attr_by_data(lxb_dom_element_t *element,
121 const lxb_dom_attr_data_t *data);
122
123 LXB_API bool
124 lxb_dom_element_compare(lxb_dom_element_t *first, lxb_dom_element_t *second);
125
126 LXB_API lxb_dom_attr_t *
127 lxb_dom_element_attr_is_exist(lxb_dom_element_t *element,
128 const lxb_char_t *qualified_name, size_t length);
129
130 LXB_API lxb_status_t
131 lxb_dom_element_is_set(lxb_dom_element_t *element,
132 const lxb_char_t *is, size_t is_len);
133
134 LXB_API lxb_status_t
135 lxb_dom_elements_by_tag_name(lxb_dom_element_t *root,
136 lxb_dom_collection_t *collection,
137 const lxb_char_t *qualified_name, size_t len);
138
139 LXB_API lxb_status_t
140 lxb_dom_elements_by_class_name(lxb_dom_element_t *root,
141 lxb_dom_collection_t *collection,
142 const lxb_char_t *class_name, size_t len);
143
144 LXB_API lxb_status_t
145 lxb_dom_elements_by_attr(lxb_dom_element_t *root,
146 lxb_dom_collection_t *collection,
147 const lxb_char_t *qualified_name, size_t qname_len,
148 const lxb_char_t *value, size_t value_len,
149 bool case_insensitive);
150
151 LXB_API lxb_status_t
152 lxb_dom_elements_by_attr_begin(lxb_dom_element_t *root,
153 lxb_dom_collection_t *collection,
154 const lxb_char_t *qualified_name, size_t qname_len,
155 const lxb_char_t *value, size_t value_len,
156 bool case_insensitive);
157
158 LXB_API lxb_status_t
159 lxb_dom_elements_by_attr_end(lxb_dom_element_t *root,
160 lxb_dom_collection_t *collection,
161 const lxb_char_t *qualified_name, size_t qname_len,
162 const lxb_char_t *value, size_t value_len,
163 bool case_insensitive);
164
165 LXB_API lxb_status_t
166 lxb_dom_elements_by_attr_contain(lxb_dom_element_t *root,
167 lxb_dom_collection_t *collection,
168 const lxb_char_t *qualified_name, size_t qname_len,
169 const lxb_char_t *value, size_t value_len,
170 bool case_insensitive);
171
172 LXB_API const lxb_char_t *
173 lxb_dom_element_qualified_name(lxb_dom_element_t *element, size_t *len);
174
175 LXB_API const lxb_char_t *
176 lxb_dom_element_qualified_name_upper(lxb_dom_element_t *element, size_t *len);
177
178 LXB_API const lxb_char_t *
179 lxb_dom_element_local_name(lxb_dom_element_t *element, size_t *len);
180
181 LXB_API const lxb_char_t *
182 lxb_dom_element_prefix(lxb_dom_element_t *element, size_t *len);
183
184 LXB_API const lxb_char_t *
185 lxb_dom_element_tag_name(lxb_dom_element_t *element, size_t *len);
186
187
188 /*
189 * Inline functions
190 */
191 lxb_inline const lxb_char_t *
lxb_dom_element_id(lxb_dom_element_t * element,size_t * len)192 lxb_dom_element_id(lxb_dom_element_t *element, size_t *len)
193 {
194 if (element->attr_id == NULL) {
195 if (len != NULL) {
196 *len = 0;
197 }
198
199 return NULL;
200 }
201
202 return lxb_dom_attr_value(element->attr_id, len);
203 }
204
205 lxb_inline const lxb_char_t *
lxb_dom_element_class(lxb_dom_element_t * element,size_t * len)206 lxb_dom_element_class(lxb_dom_element_t *element, size_t *len)
207 {
208 if (element->attr_class == NULL) {
209 if (len != NULL) {
210 *len = 0;
211 }
212
213 return NULL;
214 }
215
216 return lxb_dom_attr_value(element->attr_class, len);
217 }
218
219 lxb_inline bool
lxb_dom_element_is_custom(lxb_dom_element_t * element)220 lxb_dom_element_is_custom(lxb_dom_element_t *element)
221 {
222 return element->custom_state & LXB_DOM_ELEMENT_CUSTOM_STATE_CUSTOM;
223 }
224
225 lxb_inline bool
lxb_dom_element_custom_is_defined(lxb_dom_element_t * element)226 lxb_dom_element_custom_is_defined(lxb_dom_element_t *element)
227 {
228 return element->custom_state & LXB_DOM_ELEMENT_CUSTOM_STATE_CUSTOM
229 || element->custom_state & LXB_DOM_ELEMENT_CUSTOM_STATE_UNCUSTOMIZED;
230 }
231
232 lxb_inline lxb_dom_attr_t *
lxb_dom_element_first_attribute(lxb_dom_element_t * element)233 lxb_dom_element_first_attribute(lxb_dom_element_t *element)
234 {
235 return element->first_attr;
236 }
237
238 lxb_inline lxb_dom_attr_t *
lxb_dom_element_next_attribute(lxb_dom_attr_t * attr)239 lxb_dom_element_next_attribute(lxb_dom_attr_t *attr)
240 {
241 return attr->next;
242 }
243
244 lxb_inline lxb_dom_attr_t *
lxb_dom_element_prev_attribute(lxb_dom_attr_t * attr)245 lxb_dom_element_prev_attribute(lxb_dom_attr_t *attr)
246 {
247 return attr->prev;
248 }
249
250 lxb_inline lxb_dom_attr_t *
lxb_dom_element_last_attribute(lxb_dom_element_t * element)251 lxb_dom_element_last_attribute(lxb_dom_element_t *element)
252 {
253 return element->last_attr;
254 }
255
256 lxb_inline lxb_dom_attr_t *
lxb_dom_element_id_attribute(lxb_dom_element_t * element)257 lxb_dom_element_id_attribute(lxb_dom_element_t *element)
258 {
259 return element->attr_id;
260 }
261
262 lxb_inline lxb_dom_attr_t *
lxb_dom_element_class_attribute(lxb_dom_element_t * element)263 lxb_dom_element_class_attribute(lxb_dom_element_t *element)
264 {
265 return element->attr_class;
266 }
267
268 lxb_inline lxb_tag_id_t
lxb_dom_element_tag_id(lxb_dom_element_t * element)269 lxb_dom_element_tag_id(lxb_dom_element_t *element)
270 {
271 return lxb_dom_interface_node(element)->local_name;
272 }
273
274 lxb_inline lxb_ns_id_t
lxb_dom_element_ns_id(lxb_dom_element_t * element)275 lxb_dom_element_ns_id(lxb_dom_element_t *element)
276 {
277 return lxb_dom_interface_node(element)->ns;
278 }
279
280
281 /*
282 * No inline functions for ABI.
283 */
284 LXB_API const lxb_char_t *
285 lxb_dom_element_id_noi(lxb_dom_element_t *element, size_t *len);
286
287 LXB_API const lxb_char_t *
288 lxb_dom_element_class_noi(lxb_dom_element_t *element, size_t *len);
289
290 LXB_API bool
291 lxb_dom_element_is_custom_noi(lxb_dom_element_t *element);
292
293 LXB_API bool
294 lxb_dom_element_custom_is_defined_noi(lxb_dom_element_t *element);
295
296 LXB_API lxb_dom_attr_t *
297 lxb_dom_element_first_attribute_noi(lxb_dom_element_t *element);
298
299 LXB_API lxb_dom_attr_t *
300 lxb_dom_element_next_attribute_noi(lxb_dom_attr_t *attr);
301
302 LXB_API lxb_dom_attr_t *
303 lxb_dom_element_prev_attribute_noi(lxb_dom_attr_t *attr);
304
305 LXB_API lxb_dom_attr_t *
306 lxb_dom_element_last_attribute_noi(lxb_dom_element_t *element);
307
308 LXB_API lxb_dom_attr_t *
309 lxb_dom_element_id_attribute_noi(lxb_dom_element_t *element);
310
311 LXB_API lxb_dom_attr_t *
312 lxb_dom_element_class_attribute_noi(lxb_dom_element_t *element);
313
314
315 #ifdef __cplusplus
316 } /* extern "C" */
317 #endif
318
319 #endif /* LEXBOR_DOM_ELEMENT_H */
320