xref: /php-src/ext/dom/lexbor/lexbor/core/in.c (revision bffab33a)
1 /*
2  * Copyright (C) 2018 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #include "lexbor/core/in.h"
8 #include "lexbor/core/str_res.h"
9 
10 
11 lexbor_in_t *
lexbor_in_create(void)12 lexbor_in_create(void)
13 {
14     return lexbor_calloc(1, sizeof(lexbor_in_t));
15 }
16 
17 lxb_status_t
lexbor_in_init(lexbor_in_t * incoming,size_t chunk_size)18 lexbor_in_init(lexbor_in_t *incoming, size_t chunk_size)
19 {
20     if (incoming == NULL) {
21         return LXB_STATUS_ERROR_OBJECT_IS_NULL;
22     }
23 
24     if (chunk_size == 0) {
25         return LXB_STATUS_ERROR_WRONG_ARGS;
26     }
27 
28     incoming->nodes = lexbor_dobject_create();
29 
30     return lexbor_dobject_init(incoming->nodes, chunk_size,
31                                sizeof(lexbor_in_node_t));
32 }
33 
34 void
lexbor_in_clean(lexbor_in_t * incoming)35 lexbor_in_clean(lexbor_in_t *incoming)
36 {
37     lexbor_dobject_clean(incoming->nodes);
38 }
39 
40 lexbor_in_t *
lexbor_in_destroy(lexbor_in_t * incoming,bool self_destroy)41 lexbor_in_destroy(lexbor_in_t *incoming, bool self_destroy)
42 {
43     if (incoming == NULL) {
44         return NULL;
45     }
46 
47     incoming->nodes = lexbor_dobject_destroy(incoming->nodes, true);
48 
49     if (self_destroy == true) {
50         return lexbor_free(incoming);
51     }
52 
53     return incoming;
54 }
55 
56 lexbor_in_node_t *
lexbor_in_node_make(lexbor_in_t * incoming,lexbor_in_node_t * last_node,const lxb_char_t * buf,size_t buf_size)57 lexbor_in_node_make(lexbor_in_t *incoming, lexbor_in_node_t *last_node,
58                     const lxb_char_t *buf, size_t buf_size)
59 {
60     lexbor_in_node_t *node = lexbor_dobject_alloc(incoming->nodes);
61 
62     if (node == NULL) {
63         return NULL;
64     }
65 
66     node->opt = LEXBOR_IN_OPT_UNDEF;
67     node->begin = buf;
68     node->end = buf + buf_size;
69     node->use = buf;
70 
71     if (last_node != NULL) {
72         last_node->next = node;
73         node->offset = last_node->offset + (last_node->end - last_node->begin);
74     }
75     else {
76         node->offset = 0;
77     }
78 
79     node->prev = last_node;
80     node->next = NULL;
81     node->incoming = incoming;
82 
83     return node;
84 }
85 
86 void
lexbor_in_node_clean(lexbor_in_node_t * node)87 lexbor_in_node_clean(lexbor_in_node_t *node)
88 {
89     lexbor_in_t *incoming = node->incoming;
90 
91     memset(node, 0, sizeof(lexbor_in_node_t));
92 
93     node->incoming = incoming;
94 }
95 
96 lexbor_in_node_t *
lexbor_in_node_destroy(lexbor_in_t * incoming,lexbor_in_node_t * node,bool self_destroy)97 lexbor_in_node_destroy(lexbor_in_t *incoming,
98                        lexbor_in_node_t *node, bool self_destroy)
99 {
100     if (node == NULL) {
101         return NULL;
102     }
103 
104     if (self_destroy) {
105         return lexbor_dobject_free(incoming->nodes, node);
106     }
107 
108     return node;
109 }
110 
111 lexbor_in_node_t *
lexbor_in_node_split(lexbor_in_node_t * node,const lxb_char_t * pos)112 lexbor_in_node_split(lexbor_in_node_t *node, const lxb_char_t *pos)
113 {
114     lexbor_in_node_t *new_node;
115 
116     new_node = lexbor_dobject_alloc(node->incoming->nodes);
117 
118     if (new_node == NULL) {
119         return NULL;
120     }
121 
122     new_node->offset   = node->offset + (pos - node->begin);
123     new_node->opt      = LEXBOR_IN_OPT_UNDEF;
124     new_node->begin    = pos;
125     new_node->end      = node->end;
126     new_node->next     = NULL;
127     new_node->prev     = node;
128     new_node->incoming = node->incoming;
129 
130     node->end  = pos;
131     node->next = new_node;
132 
133     if (node->use > pos) {
134         new_node->use = node->use;
135         node->use = pos;
136     }
137     else {
138         new_node->use = pos;
139     }
140 
141     return new_node;
142 }
143 
144 lexbor_in_node_t *
lexbor_in_node_find(lexbor_in_node_t * node,const lxb_char_t * pos)145 lexbor_in_node_find(lexbor_in_node_t *node, const lxb_char_t *pos)
146 {
147     while (node->next) {
148         node = node->next;
149     }
150 
151     while (node && (node->begin > pos || node->end < pos)) {
152         node = node->prev;
153     }
154 
155     return node;
156 }
157 
158 const lxb_char_t *
lexbor_in_node_pos_up(lexbor_in_node_t * node,lexbor_in_node_t ** return_node,const lxb_char_t * pos,size_t offset)159 lexbor_in_node_pos_up(lexbor_in_node_t *node, lexbor_in_node_t **return_node,
160                       const lxb_char_t *pos, size_t offset)
161 {
162     do {
163         pos = pos + offset;
164 
165         if (node->end >= pos) {
166             if (return_node != NULL && *return_node != node) {
167                 *return_node = node;
168             }
169 
170             return pos;
171         }
172 
173         if (node->next == NULL) {
174             if (return_node != NULL && *return_node != node) {
175                 *return_node = node;
176             }
177 
178             return node->end;
179         }
180 
181         offset = pos - node->end;
182         node = node->next;
183         pos = node->begin;
184 
185     }
186     while (1);
187 
188     return NULL;
189 }
190 
191 const lxb_char_t *
lexbor_in_node_pos_down(lexbor_in_node_t * node,lexbor_in_node_t ** return_node,const lxb_char_t * pos,size_t offset)192 lexbor_in_node_pos_down(lexbor_in_node_t *node, lexbor_in_node_t **return_node,
193                         const lxb_char_t *pos, size_t offset)
194 {
195     do {
196         pos = pos - offset;
197 
198         if (node->begin <= pos) {
199             if (return_node != NULL && *return_node != node) {
200                 *return_node = node;
201             }
202 
203             return pos;
204         }
205 
206         if (node->prev == NULL) {
207             if (return_node != NULL && *return_node != node) {
208                 *return_node = node;
209             }
210 
211             return node->begin;
212         }
213 
214         offset = node->begin - pos;
215         node = node->prev;
216         pos = node->end;
217 
218     }
219     while (1);
220 
221     return NULL;
222 }
223 
224 /*
225 * No inline functions for ABI.
226 */
227 const lxb_char_t *
lexbor_in_node_begin_noi(const lexbor_in_node_t * node)228 lexbor_in_node_begin_noi(const lexbor_in_node_t *node)
229 {
230     return lexbor_in_node_begin(node);
231 }
232 
233 const lxb_char_t *
lexbor_in_node_end_noi(const lexbor_in_node_t * node)234 lexbor_in_node_end_noi(const lexbor_in_node_t *node)
235 {
236     return lexbor_in_node_end(node);
237 }
238 
239 size_t
lexbor_in_node_offset_noi(const lexbor_in_node_t * node)240 lexbor_in_node_offset_noi(const lexbor_in_node_t *node)
241 {
242     return lexbor_in_node_offset(node);
243 }
244 
245 lexbor_in_node_t *
lexbor_in_node_next_noi(const lexbor_in_node_t * node)246 lexbor_in_node_next_noi(const lexbor_in_node_t *node)
247 {
248     return lexbor_in_node_next(node);
249 }
250 
251 lexbor_in_node_t *
lexbor_in_node_prev_noi(const lexbor_in_node_t * node)252 lexbor_in_node_prev_noi(const lexbor_in_node_t *node)
253 {
254     return lexbor_in_node_prev(node);
255 }
256 
257 lexbor_in_t *
lexbor_in_node_in_noi(const lexbor_in_node_t * node)258 lexbor_in_node_in_noi(const lexbor_in_node_t *node)
259 {
260     return lexbor_in_node_in(node);
261 }
262 
263 bool
lexbor_in_segment_noi(const lexbor_in_node_t * node,const lxb_char_t * data)264 lexbor_in_segment_noi(const lexbor_in_node_t *node, const lxb_char_t *data)
265 {
266     return lexbor_in_segment(node, data);
267 }
268