Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | Copyright 2022 Joel Svensson svenssonjoel@yahoo.se | ||
3 | |||
4 | This program is free software: you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation, either version 3 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #include <lbm_channel.h> | ||
19 | #include <string.h> | ||
20 | |||
21 | /* ------------------------------------------------------------ | ||
22 | Interface | ||
23 | ------------------------------------------------------------ */ | ||
24 | 2941916 | bool lbm_channel_more(lbm_char_channel_t *chan) { | |
25 | 2941916 | return chan->more(chan); | |
26 | } | ||
27 | |||
28 | 32224918 | int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) { | |
29 | 32224918 | return chan->peek(chan, n, res); | |
30 | } | ||
31 | |||
32 | ✗ | bool lbm_channel_read(lbm_char_channel_t *chan, char *res) { | |
33 | ✗ | return chan->read(chan, res); | |
34 | } | ||
35 | |||
36 | 3371876 | bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) { | |
37 | 3371876 | return chan->drop(chan, n); | |
38 | } | ||
39 | |||
40 | 1474973 | bool lbm_channel_comment(lbm_char_channel_t *chan) { | |
41 | 1474973 | return chan->comment(chan); | |
42 | } | ||
43 | |||
44 | 8004 | void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) { | |
45 | 8004 | chan->set_comment(chan, comment); | |
46 | 8004 | } | |
47 | |||
48 | 2342795 | bool lbm_channel_is_empty(lbm_char_channel_t *chan) { | |
49 | 2342795 | return chan->channel_is_empty(chan); | |
50 | } | ||
51 | |||
52 | ✗ | bool lbm_channel_is_full(lbm_char_channel_t *chan) { | |
53 | ✗ | return chan->channel_is_full(chan); | |
54 | } | ||
55 | |||
56 | 2416273 | int lbm_channel_write(lbm_char_channel_t *chan, char c) { | |
57 | 2416273 | return chan->write(chan, c); | |
58 | } | ||
59 | |||
60 | 8722 | void lbm_channel_writer_close(lbm_char_channel_t *chan) { | |
61 | 8722 | chan->writer_close(chan); | |
62 | 8722 | } | |
63 | |||
64 | 34682 | void lbm_channel_reader_close(lbm_char_channel_t *chan) { | |
65 | 34682 | chan->reader_close(chan); | |
66 | 34682 | } | |
67 | |||
68 | ✗ | bool lbm_channel_reader_is_closed(lbm_char_channel_t *chan) { | |
69 | ✗ | return chan->reader_is_closed(chan); | |
70 | } | ||
71 | |||
72 | 51620 | unsigned int lbm_channel_row(lbm_char_channel_t *chan) { | |
73 | 51620 | return chan->row(chan); | |
74 | } | ||
75 | |||
76 | ✗ | unsigned int lbm_channel_column(lbm_char_channel_t *chan) { | |
77 | ✗ | return chan->column(chan); | |
78 | } | ||
79 | |||
80 | /* ------------------------------------------------------------ | ||
81 | Implementation buffered channel | ||
82 | ------------------------------------------------------------ */ | ||
83 | |||
84 | 1353176 | bool buffered_more(lbm_char_channel_t *chan) { | |
85 | 1353176 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
86 | 1353176 | return st->more; | |
87 | } | ||
88 | |||
89 | 8722 | void buffered_writer_close(lbm_char_channel_t *chan) { | |
90 | 8722 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
91 | 8722 | st->more = false; | |
92 | 8722 | } | |
93 | |||
94 | 8714 | void buffered_reader_close(lbm_char_channel_t *chan) { | |
95 | 8714 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
96 | 8714 | st->reader_closed = true; | |
97 | 8714 | } | |
98 | |||
99 | ✗ | bool buffered_reader_is_closed(lbm_char_channel_t *chan) { | |
100 | ✗ | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
101 | ✗ | return st->reader_closed; | |
102 | } | ||
103 | |||
104 | 14996312 | int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) { | |
105 | 14996312 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
106 | 14996312 | char *buffer = st->buffer; | |
107 | 14996312 | int ret = CHANNEL_MORE; | |
108 | 14996312 | mutex_lock(&st->lock); | |
109 | 14996312 | unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE; | |
110 | bool in_data; | ||
111 | |||
112 |
2/2✓ Branch 0 taken 7215191 times.
✓ Branch 1 taken 7781121 times.
|
14996312 | if (st->write_pos >= st->read_pos) { |
113 |
3/4✓ Branch 0 taken 7205890 times.
✓ Branch 1 taken 9301 times.
✓ Branch 2 taken 7205890 times.
✗ Branch 3 not taken.
|
7215191 | in_data = peek_pos < st->write_pos && peek_pos >= st->read_pos; |
114 | } else { | ||
115 |
3/4✓ Branch 0 taken 7753163 times.
✓ Branch 1 taken 27958 times.
✓ Branch 2 taken 7753163 times.
✗ Branch 3 not taken.
|
7781121 | in_data = !(peek_pos >= st->write_pos && peek_pos < st->read_pos); |
116 | } | ||
117 | |||
118 |
2/2✓ Branch 0 taken 14987011 times.
✓ Branch 1 taken 9301 times.
|
14996312 | if (in_data) { |
119 | 14987011 | *res = buffer[peek_pos]; | |
120 | 14987011 | ret = CHANNEL_SUCCESS; | |
121 |
2/2✓ Branch 1 taken 8630 times.
✓ Branch 2 taken 671 times.
|
9301 | } else if (!buffered_more(chan)) { |
122 | 8630 | ret = CHANNEL_END; | |
123 |
1/2✓ Branch 1 taken 671 times.
✗ Branch 2 not taken.
|
671 | } else if (buffered_more(chan)) { |
124 | 671 | ret = CHANNEL_MORE; | |
125 | } | ||
126 | 14996312 | mutex_unlock(&st->lock); | |
127 | 14996312 | return ret; | |
128 | } | ||
129 | |||
130 | 3095823 | bool buffered_channel_is_empty(lbm_char_channel_t *chan) { | |
131 | 3095823 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
132 |
2/2✓ Branch 0 taken 8714 times.
✓ Branch 1 taken 3087109 times.
|
3095823 | if (st->read_pos == st->write_pos) { |
133 | 8714 | return true; | |
134 | } | ||
135 | 3087109 | return false; | |
136 | } | ||
137 | |||
138 | 2369961 | bool buffered_channel_is_full(lbm_char_channel_t *chan) { | |
139 | 2369961 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
140 |
2/2✓ Branch 0 taken 2356093 times.
✓ Branch 1 taken 13868 times.
|
2369961 | if (st->write_pos == st->read_pos - 1 || |
141 |
2/2✓ Branch 0 taken 1139048 times.
✓ Branch 1 taken 1217045 times.
|
2356093 | (st->read_pos == 0 && |
142 |
2/2✓ Branch 0 taken 4163 times.
✓ Branch 1 taken 1134885 times.
|
1139048 | st->write_pos == TOKENIZER_BUFFER_SIZE-1)) { |
143 | 18031 | return true; | |
144 | } | ||
145 | 2351930 | return false; | |
146 | } | ||
147 | |||
148 | 2351740 | bool buffered_read(lbm_char_channel_t *chan, char *res) { | |
149 | 2351740 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
150 | 2351740 | char *buffer = st->buffer; | |
151 | 2351740 | bool ret = false; | |
152 | 2351740 | mutex_lock(&st->lock); | |
153 |
1/2✓ Branch 1 taken 2351740 times.
✗ Branch 2 not taken.
|
2351740 | if (!buffered_channel_is_empty(chan)) { |
154 | 2351740 | *res = buffer[st->read_pos]; | |
155 | 2351740 | st->column++; | |
156 |
2/2✓ Branch 0 taken 72522 times.
✓ Branch 1 taken 2279218 times.
|
2351740 | if (*res == '\n') { |
157 | 72522 | st->column = 0; | |
158 | 72522 | st->row ++; | |
159 | } | ||
160 | 2351740 | st->read_pos = (st->read_pos + 1) % TOKENIZER_BUFFER_SIZE; | |
161 | 2351740 | ret = true; | |
162 | } | ||
163 | 2351740 | mutex_unlock(&st->lock); | |
164 | 2351740 | return ret; | |
165 | } | ||
166 | |||
167 | 1598526 | bool buffered_drop(lbm_char_channel_t *chan, unsigned int n) { | |
168 | 1598526 | bool r = true; | |
169 | char c; | ||
170 | |||
171 |
2/2✓ Branch 0 taken 2351740 times.
✓ Branch 1 taken 1598526 times.
|
3950266 | for (unsigned int i = 0; i < n; i ++) { |
172 | 2351740 | r = buffered_read(chan, &c); | |
173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2351740 times.
|
2351740 | if (r == false) break; |
174 | } | ||
175 | 1598526 | return r; | |
176 | } | ||
177 | |||
178 | 2369961 | int buffered_write(lbm_char_channel_t *chan, char c) { | |
179 | 2369961 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2369961 times.
|
2369961 | if (st->reader_closed) return CHANNEL_READER_CLOSED; |
181 | 2369961 | int ret = CHANNEL_FULL; | |
182 | 2369961 | mutex_lock(&st->lock); | |
183 | 2369961 | char *buffer = st->buffer; | |
184 |
2/2✓ Branch 1 taken 2351930 times.
✓ Branch 2 taken 18031 times.
|
2369961 | if (!buffered_channel_is_full(chan)) { |
185 | 2351930 | buffer[st->write_pos] = c; | |
186 | 2351930 | st->write_pos = (st->write_pos + 1) % TOKENIZER_BUFFER_SIZE; | |
187 | 2351930 | ret = CHANNEL_SUCCESS; | |
188 | } | ||
189 | 2369961 | mutex_unlock(&st->lock); | |
190 | 2369961 | return ret; | |
191 | } | ||
192 | |||
193 | 29927 | unsigned int buffered_row(lbm_char_channel_t *chan) { | |
194 | 29927 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
195 | 29927 | return st->row; | |
196 | } | ||
197 | |||
198 | ✗ | unsigned int buffered_column(lbm_char_channel_t *chan) { | |
199 | ✗ | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
200 | ✗ | return st->column; | |
201 | } | ||
202 | |||
203 | 673895 | bool buffered_comment(lbm_char_channel_t *chan) { | |
204 | 673895 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
205 | 673895 | return st->comment; | |
206 | } | ||
207 | |||
208 | 4000 | void buffered_set_comment(lbm_char_channel_t *chan, bool comment) { | |
209 | 4000 | lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state; | |
210 | 4000 | st->comment = comment; | |
211 | 4000 | } | |
212 | |||
213 | 8722 | void lbm_create_buffered_char_channel(lbm_buffered_channel_state_t *st, | |
214 | lbm_char_channel_t *chan) { | ||
215 | |||
216 | 8722 | st->write_pos = 0; | |
217 | 8722 | st->read_pos = 0; | |
218 | 8722 | st->more = true; | |
219 | 8722 | st->reader_closed = false; | |
220 | 8722 | st->comment = false; | |
221 | 8722 | st->row = 1; | |
222 | 8722 | st->column = 1; | |
223 | |||
224 |
1/2✓ Branch 0 taken 8722 times.
✗ Branch 1 not taken.
|
8722 | if (!st->mutex_initialized) { |
225 | 8722 | mutex_init(&st->lock); | |
226 | 8722 | st->mutex_initialized = true; | |
227 | } | ||
228 | |||
229 | 8722 | chan->state = st; | |
230 | 8722 | chan->more = buffered_more; | |
231 | 8722 | chan->peek = buffered_peek; | |
232 | 8722 | chan->read = buffered_read; | |
233 | 8722 | chan->drop = buffered_drop; | |
234 | 8722 | chan->comment = buffered_comment; | |
235 | 8722 | chan->set_comment = buffered_set_comment; | |
236 | 8722 | chan->channel_is_empty = buffered_channel_is_empty; | |
237 | 8722 | chan->channel_is_full = buffered_channel_is_full; | |
238 | 8722 | chan->write = buffered_write; | |
239 | 8722 | chan->writer_close = buffered_writer_close; | |
240 | 8722 | chan->reader_close = buffered_reader_close; | |
241 | 8722 | chan->reader_is_closed = buffered_reader_is_closed; | |
242 | 8722 | chan->row = buffered_row; | |
243 | 8722 | chan->column = buffered_column; | |
244 | 8722 | } | |
245 | |||
246 | /* ------------------------------------------------------------ | ||
247 | Implementation string channel | ||
248 | ------------------------------------------------------------ */ | ||
249 | |||
250 | 1598712 | bool string_more(lbm_char_channel_t *chan) { | |
251 | 1598712 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
252 | 1598712 | return st->more; | |
253 | } | ||
254 | |||
255 | ✗ | void string_writer_close(lbm_char_channel_t *chan) { | |
256 | ✗ | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
257 | ✗ | st->more = false; | |
258 | ✗ | } | |
259 | |||
260 | 25968 | void string_reader_close(lbm_char_channel_t *chan) { | |
261 | 25968 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
262 | 25968 | st->reader_closed = true; | |
263 | 25968 | } | |
264 | |||
265 | ✗ | bool string_reader_is_closed(lbm_char_channel_t *chan) { | |
266 | ✗ | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
267 | ✗ | return st->reader_closed; | |
268 | } | ||
269 | |||
270 | 17228606 | int string_peek(lbm_char_channel_t *chan, unsigned int n, char *res) { | |
271 | 17228606 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
272 | 17228606 | char *str = st->str; | |
273 | |||
274 | 17228606 | unsigned int peek_pos = st->read_pos + n; | |
275 | |||
276 |
2/2✓ Branch 0 taken 17207622 times.
✓ Branch 1 taken 20984 times.
|
17228606 | if (peek_pos < st->length) { |
277 | 17207622 | *res = str[peek_pos]; | |
278 | 17207622 | return CHANNEL_SUCCESS; | |
279 | } | ||
280 | 20984 | return CHANNEL_END; | |
281 | } | ||
282 | |||
283 | 1598712 | bool string_channel_is_empty(lbm_char_channel_t *chan) { | |
284 | 1598712 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
285 |
2/2✓ Branch 0 taken 9196 times.
✓ Branch 1 taken 1589516 times.
|
1598712 | if (st->read_pos == st->length) { |
286 | 9196 | return true; | |
287 | } | ||
288 | 1589516 | return false; | |
289 | } | ||
290 | |||
291 | ✗ | bool string_channel_is_full(lbm_char_channel_t *chan) { | |
292 | ✗ | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
293 | ✗ | if (st->write_pos == st->length) { | |
294 | ✗ | return true; | |
295 | } | ||
296 | ✗ | return false; | |
297 | } | ||
298 | |||
299 | 2778116 | bool string_read(lbm_char_channel_t *chan, char *res) { | |
300 | 2778116 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
301 | 2778116 | char *str = st->str; | |
302 | |||
303 |
1/2✓ Branch 0 taken 2778116 times.
✗ Branch 1 not taken.
|
2778116 | if (st->read_pos < st->length) { |
304 | 2778116 | *res = str[st->read_pos]; | |
305 |
2/2✓ Branch 0 taken 72532 times.
✓ Branch 1 taken 2705584 times.
|
2778116 | if (*res == '\n') { |
306 | 72532 | st->row ++; | |
307 | 72532 | st->column = 1; | |
308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2705584 times.
|
2705584 | } else if (*res == 0) { |
309 | ✗ | st->more = false; | |
310 | } else { | ||
311 | 2705584 | st->column++; | |
312 | } | ||
313 | 2778116 | st->read_pos = st->read_pos + 1; | |
314 | } else { | ||
315 | ✗ | st->more = false; | |
316 | } | ||
317 | 2778116 | return true; | |
318 | } | ||
319 | |||
320 | 1773350 | bool string_drop(lbm_char_channel_t *chan, unsigned int n) { | |
321 | 1773350 | bool r = true; | |
322 | char c; | ||
323 | |||
324 |
1/2✓ Branch 0 taken 1773350 times.
✗ Branch 1 not taken.
|
1773350 | if (n > 0) { |
325 | do { | ||
326 | 2778116 | r = string_read(chan, &c); | |
327 | 2778116 | n--; | |
328 |
3/4✓ Branch 0 taken 1004766 times.
✓ Branch 1 taken 1773350 times.
✓ Branch 2 taken 1004766 times.
✗ Branch 3 not taken.
|
2778116 | } while (n > 0 && r); |
329 | } | ||
330 | 1773350 | return r; | |
331 | } | ||
332 | |||
333 | 46313 | int string_write(lbm_char_channel_t *chan, char c) { | |
334 | 46313 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
335 | 46313 | char *str = st->str; | |
336 | |||
337 |
2/2✓ Branch 0 taken 46305 times.
✓ Branch 1 taken 8 times.
|
46313 | if (st->write_pos < st->length - 1) { |
338 | 46305 | str[st->write_pos] = c; | |
339 | 46305 | st->write_pos = st->write_pos + 1; | |
340 | } else { | ||
341 | 8 | return CHANNEL_FULL; | |
342 | } | ||
343 | 46305 | return CHANNEL_SUCCESS; | |
344 | } | ||
345 | |||
346 | 47453 | unsigned int string_row(lbm_char_channel_t *chan) { | |
347 | 47453 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
348 | 47453 | return st->row; | |
349 | } | ||
350 | |||
351 | ✗ | unsigned int string_column(lbm_char_channel_t *chan) { | |
352 | ✗ | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
353 | ✗ | return st->column; | |
354 | } | ||
355 | |||
356 | 801078 | bool string_comment(lbm_char_channel_t *chan) { | |
357 | 801078 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
358 | 801078 | return st->comment; | |
359 | } | ||
360 | |||
361 | 4004 | void string_set_comment(lbm_char_channel_t *chan, bool comment) { | |
362 | 4004 | lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state; | |
363 | 4004 | st->comment = comment; | |
364 | 4004 | } | |
365 | |||
366 | 25982 | void lbm_create_string_char_channel(lbm_string_channel_state_t *st, | |
367 | lbm_char_channel_t *chan, | ||
368 | char *str) { | ||
369 | |||
370 | 25982 | st->str = str; | |
371 | 25982 | st->length = (unsigned int)strlen(str); | |
372 | 25982 | st->read_pos = 0; | |
373 | 25982 | st->write_pos = 0; | |
374 | 25982 | st->more = false; | |
375 | 25982 | st->comment = false; | |
376 | 25982 | st->row = 1; | |
377 | 25982 | st->column = 1; | |
378 | |||
379 | 25982 | chan->state = st; | |
380 | 25982 | chan->more = string_more; | |
381 | 25982 | chan->peek = string_peek; | |
382 | 25982 | chan->read = string_read; | |
383 | 25982 | chan->drop = string_drop; | |
384 | 25982 | chan->comment = string_comment; | |
385 | 25982 | chan->set_comment = string_set_comment; | |
386 | 25982 | chan->channel_is_empty = string_channel_is_empty; | |
387 | 25982 | chan->channel_is_full = string_channel_is_full; | |
388 | 25982 | chan->write = string_write; | |
389 | 25982 | chan->writer_close = string_writer_close; | |
390 | 25982 | chan->reader_close = string_reader_close; | |
391 | 25982 | chan->reader_is_closed = string_reader_is_closed; | |
392 | 25982 | chan->row = string_row; | |
393 | 25982 | chan->column = string_column; | |
394 | 25982 | } | |
395 | |||
396 | 36523 | void lbm_create_string_char_channel_size(lbm_string_channel_state_t *st, | |
397 | lbm_char_channel_t *chan, | ||
398 | char *str, | ||
399 | unsigned int size) { | ||
400 | 36523 | st->str = str; | |
401 | 36523 | st->length = size; | |
402 | 36523 | st->read_pos = 0; | |
403 | 36523 | st->write_pos = 0; | |
404 | 36523 | st->more = false; | |
405 | 36523 | st->comment = false; | |
406 | 36523 | st->row = 1; | |
407 | 36523 | st->column = 1; | |
408 | |||
409 | 36523 | chan->state = st; | |
410 | 36523 | chan->more = string_more; | |
411 | 36523 | chan->peek = string_peek; | |
412 | 36523 | chan->read = string_read; | |
413 | 36523 | chan->drop = string_drop; | |
414 | 36523 | chan->comment = string_comment; | |
415 | 36523 | chan->set_comment = string_set_comment; | |
416 | 36523 | chan->channel_is_empty = string_channel_is_empty; | |
417 | 36523 | chan->channel_is_full = string_channel_is_full; | |
418 | 36523 | chan->write = string_write; | |
419 | 36523 | chan->writer_close = string_writer_close; | |
420 | 36523 | chan->reader_close = string_reader_close; | |
421 | 36523 | chan->reader_is_closed = string_reader_is_closed; | |
422 | 36523 | chan->row = string_row; | |
423 | 36523 | chan->column = string_column; | |
424 | 36523 | } | |
425 |