1 /*
2 * Copyright (C) 2018-2021 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #ifndef LEXBOR_DOM_NODE_H
8 #define LEXBOR_DOM_NODE_H
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 #include "lexbor/dom/interface.h"
15 #include "lexbor/dom/collection.h"
16 #include "lexbor/dom/interfaces/event_target.h"
17
18
19 typedef lexbor_action_t
20 (*lxb_dom_node_simple_walker_f)(lxb_dom_node_t *node, void *ctx);
21
22
23 typedef enum {
24 LXB_DOM_NODE_TYPE_UNDEF = 0x00,
25 LXB_DOM_NODE_TYPE_ELEMENT = 0x01,
26 LXB_DOM_NODE_TYPE_ATTRIBUTE = 0x02,
27 LXB_DOM_NODE_TYPE_TEXT = 0x03,
28 LXB_DOM_NODE_TYPE_CDATA_SECTION = 0x04,
29 LXB_DOM_NODE_TYPE_ENTITY_REFERENCE = 0x05, // historical
30 LXB_DOM_NODE_TYPE_ENTITY = 0x06, // historical
31 LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION = 0x07,
32 LXB_DOM_NODE_TYPE_COMMENT = 0x08,
33 LXB_DOM_NODE_TYPE_DOCUMENT = 0x09,
34 LXB_DOM_NODE_TYPE_DOCUMENT_TYPE = 0x0A,
35 LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT = 0x0B,
36 LXB_DOM_NODE_TYPE_NOTATION = 0x0C, // historical
37 LXB_DOM_NODE_TYPE_LAST_ENTRY = 0x0D
38 }
39 lxb_dom_node_type_t;
40
41 struct lxb_dom_node {
42 lxb_dom_event_target_t event_target;
43
44 /* For example: <LalAla:DiV Fix:Me="value"> */
45
46 uintptr_t local_name; /* , lowercase, without prefix: div */
47 uintptr_t prefix; /* lowercase: lalala */
48 uintptr_t ns; /* namespace */
49
50 lxb_dom_document_t *owner_document;
51
52 lxb_dom_node_t *next;
53 lxb_dom_node_t *prev;
54 lxb_dom_node_t *parent;
55 lxb_dom_node_t *first_child;
56 lxb_dom_node_t *last_child;
57 void *user;
58
59 lxb_dom_node_type_t type;
60
61 size_t line;
62
63 #ifdef LXB_DOM_NODE_USER_VARIABLES
64 LXB_DOM_NODE_USER_VARIABLES
65 #endif /* LXB_DOM_NODE_USER_VARIABLES */
66 };
67
68
69 LXB_API lxb_dom_node_t *
70 lxb_dom_node_interface_create(lxb_dom_document_t *document);
71
72 LXB_API lxb_dom_node_t *
73 lxb_dom_node_interface_clone(lxb_dom_document_t *document,
74 const lxb_dom_node_t *node, bool is_attr);
75
76 LXB_API lxb_dom_node_t *
77 lxb_dom_node_interface_destroy(lxb_dom_node_t *node);
78
79 LXB_API lxb_status_t
80 lxb_dom_node_interface_copy(lxb_dom_node_t *dst,
81 const lxb_dom_node_t *src, bool is_attr);
82
83 LXB_API lxb_dom_node_t *
84 lxb_dom_node_destroy(lxb_dom_node_t *node);
85
86 LXB_API lxb_dom_node_t *
87 lxb_dom_node_destroy_deep(lxb_dom_node_t *root);
88
89 LXB_API lxb_dom_node_t *
90 lxb_dom_node_clone(lxb_dom_node_t *node, bool deep);
91
92 LXB_API const lxb_char_t *
93 lxb_dom_node_name(lxb_dom_node_t *node, size_t *len);
94
95 LXB_API void
96 lxb_dom_node_insert_child_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node);
97
98 LXB_API void
99 lxb_dom_node_insert_child(lxb_dom_node_t *to, lxb_dom_node_t *node);
100
101 LXB_API void
102 lxb_dom_node_insert_before_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node);
103
104 LXB_API void
105 lxb_dom_node_insert_before(lxb_dom_node_t *to, lxb_dom_node_t *node);
106
107 LXB_API void
108 lxb_dom_node_insert_after_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node);
109
110 LXB_API void
111 lxb_dom_node_insert_after(lxb_dom_node_t *to, lxb_dom_node_t *node);
112
113 LXB_API void
114 lxb_dom_node_remove_wo_events(lxb_dom_node_t *node);
115
116 LXB_API void
117 lxb_dom_node_remove(lxb_dom_node_t *node);
118
119 LXB_API lxb_status_t
120 lxb_dom_node_replace_all(lxb_dom_node_t *parent, lxb_dom_node_t *node);
121
122 LXB_API void
123 lxb_dom_node_simple_walk(lxb_dom_node_t *root,
124 lxb_dom_node_simple_walker_f walker_cb, void *ctx);
125
126 LXB_API lxb_status_t
127 lxb_dom_node_by_tag_name(lxb_dom_node_t *root, lxb_dom_collection_t *collection,
128 const lxb_char_t *qualified_name, size_t len);
129 LXB_API lxb_status_t
130 lxb_dom_node_by_class_name(lxb_dom_node_t *root,
131 lxb_dom_collection_t *collection,
132 const lxb_char_t *class_name, size_t len);
133 LXB_API lxb_status_t
134 lxb_dom_node_by_attr(lxb_dom_node_t *root, lxb_dom_collection_t *collection,
135 const lxb_char_t *qualified_name, size_t qname_len,
136 const lxb_char_t *value, size_t value_len,
137 bool case_insensitive);
138 LXB_API lxb_status_t
139 lxb_dom_node_by_attr_begin(lxb_dom_node_t *root,
140 lxb_dom_collection_t *collection,
141 const lxb_char_t *qualified_name, size_t qname_len,
142 const lxb_char_t *value, size_t value_len,
143 bool case_insensitive);
144 LXB_API lxb_status_t
145 lxb_dom_node_by_attr_end(lxb_dom_node_t *root, lxb_dom_collection_t *collection,
146 const lxb_char_t *qualified_name, size_t qname_len,
147 const lxb_char_t *value, size_t value_len,
148 bool case_insensitive);
149 LXB_API lxb_status_t
150 lxb_dom_node_by_attr_contain(lxb_dom_node_t *root,
151 lxb_dom_collection_t *collection,
152 const lxb_char_t *qualified_name, size_t qname_len,
153 const lxb_char_t *value, size_t value_len,
154 bool case_insensitive);
155
156 /*
157 * Memory of returns value will be freed in document destroy moment.
158 * If you need to release returned resource after use, then call the
159 * lxb_dom_document_destroy_text(node->owner_document, text) function.
160 */
161 LXB_API lxb_char_t *
162 lxb_dom_node_text_content(lxb_dom_node_t *node, size_t *len);
163
164 LXB_API lxb_status_t
165 lxb_dom_node_text_content_set(lxb_dom_node_t *node,
166 const lxb_char_t *content, size_t len);
167
168 LXB_API bool
169 lxb_dom_node_is_empty(const lxb_dom_node_t *root);
170
171
172 /*
173 * Inline functions
174 */
175 lxb_inline lxb_tag_id_t
lxb_dom_node_tag_id(lxb_dom_node_t * node)176 lxb_dom_node_tag_id(lxb_dom_node_t *node)
177 {
178 return node->local_name;
179 }
180
181 lxb_inline lxb_dom_node_t *
lxb_dom_node_next(lxb_dom_node_t * node)182 lxb_dom_node_next(lxb_dom_node_t *node)
183 {
184 return node->next;
185 }
186
187 lxb_inline lxb_dom_node_t *
lxb_dom_node_prev(lxb_dom_node_t * node)188 lxb_dom_node_prev(lxb_dom_node_t *node)
189 {
190 return node->prev;
191 }
192
193 lxb_inline lxb_dom_node_t *
lxb_dom_node_parent(lxb_dom_node_t * node)194 lxb_dom_node_parent(lxb_dom_node_t *node)
195 {
196 return node->parent;
197 }
198
199 lxb_inline lxb_dom_node_t *
lxb_dom_node_first_child(lxb_dom_node_t * node)200 lxb_dom_node_first_child(lxb_dom_node_t *node)
201 {
202 return node->first_child;
203 }
204
205 lxb_inline lxb_dom_node_t *
lxb_dom_node_last_child(lxb_dom_node_t * node)206 lxb_dom_node_last_child(lxb_dom_node_t *node)
207 {
208 return node->last_child;
209 }
210
211 /*
212 * No inline functions for ABI.
213 */
214 LXB_API lxb_tag_id_t
215 lxb_dom_node_tag_id_noi(lxb_dom_node_t *node);
216
217 LXB_API lxb_dom_node_t *
218 lxb_dom_node_next_noi(lxb_dom_node_t *node);
219
220 LXB_API lxb_dom_node_t *
221 lxb_dom_node_prev_noi(lxb_dom_node_t *node);
222
223 LXB_API lxb_dom_node_t *
224 lxb_dom_node_parent_noi(lxb_dom_node_t *node);
225
226 LXB_API lxb_dom_node_t *
227 lxb_dom_node_first_child_noi(lxb_dom_node_t *node);
228
229 LXB_API lxb_dom_node_t *
230 lxb_dom_node_last_child_noi(lxb_dom_node_t *node);
231
232
233 #ifdef __cplusplus
234 } /* extern "C" */
235 #endif
236
237 #endif /* LEXBOR_DOM_NODE_H */
238