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