GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_channel.c
Date: 2024-11-05 17:11:09
Exec Total Coverage
Lines: 255 286 89.2%
Functions: 39 49 79.6%
Branches: 45 58 77.6%

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 #include <lbm_defines.h>
21
22 /* ------------------------------------------------------------
23 Interface
24 ------------------------------------------------------------ */
25 11385349 bool lbm_channel_more(lbm_char_channel_t *chan) {
26 11385349 return chan->more(chan);
27 }
28
29 145243789 int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
30 145243789 return chan->peek(chan, n, res);
31 }
32
33 bool lbm_channel_read(lbm_char_channel_t *chan, char *res) {
34 return chan->read(chan, res);
35 }
36
37 10845512 bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) {
38 10845512 return chan->drop(chan, n);
39 }
40
41 5692535 bool lbm_channel_comment(lbm_char_channel_t *chan) {
42 5692535 return chan->comment(chan);
43 }
44
45 10975 void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) {
46 10975 chan->set_comment(chan, comment);
47 10975 }
48
49 10564000 bool lbm_channel_is_empty(lbm_char_channel_t *chan) {
50 10564000 return chan->channel_is_empty(chan);
51 }
52
53 bool lbm_channel_is_full(lbm_char_channel_t *chan) {
54 return chan->channel_is_full(chan);
55 }
56
57 3286996 int lbm_channel_write(lbm_char_channel_t *chan, char c) {
58 3286996 return chan->write(chan, c);
59 }
60
61 10752 void lbm_channel_writer_close(lbm_char_channel_t *chan) {
62 10752 chan->writer_close(chan);
63 10752 }
64
65 330223 void lbm_channel_reader_close(lbm_char_channel_t *chan) {
66 330223 chan->reader_close(chan);
67 330223 }
68
69 bool lbm_channel_reader_is_closed(lbm_char_channel_t *chan) {
70 return chan->reader_is_closed(chan);
71 }
72
73 377987 unsigned int lbm_channel_row(lbm_char_channel_t *chan) {
74 377987 return chan->row(chan);
75 }
76
77 unsigned int lbm_channel_column(lbm_char_channel_t *chan) {
78 return chan->column(chan);
79 }
80
81 26292 bool lbm_channel_may_block(lbm_char_channel_t *chan) {
82 26292 return chan->may_block(chan);
83 }
84
85 /* ------------------------------------------------------------
86 Implementation buffered channel
87 ------------------------------------------------------------ */
88 10752 bool buffered_may_block(lbm_char_channel_t *chan) {
89 (void) chan;
90 10752 return true;
91 }
92
93 1806594 bool buffered_more(lbm_char_channel_t *chan) {
94 1806594 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
95 1806594 return st->more;
96 }
97
98 10752 void buffered_writer_close(lbm_char_channel_t *chan) {
99 10752 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
100 10752 st->more = false;
101 10752 }
102
103 10746 void buffered_reader_close(lbm_char_channel_t *chan) {
104 10746 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
105 10746 st->reader_closed = true;
106 10746 }
107
108 bool buffered_reader_is_closed(lbm_char_channel_t *chan) {
109 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
110 return st->reader_closed;
111 }
112
113 18384769 int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
114 18384769 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
115 18384769 char *buffer = st->buffer;
116 18384769 int ret = CHANNEL_MORE;
117 18384769 mutex_lock(&st->lock);
118 18384769 unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE;
119 bool in_data;
120
121
2/2
✓ Branch 0 taken 8652858 times.
✓ Branch 1 taken 9731911 times.
18384769 if (st->write_pos >= st->read_pos) {
122
3/4
✓ Branch 0 taken 8641585 times.
✓ Branch 1 taken 11273 times.
✓ Branch 2 taken 8641585 times.
✗ Branch 3 not taken.
8652858 in_data = peek_pos < st->write_pos && peek_pos >= st->read_pos;
123 } else {
124
3/4
✓ Branch 0 taken 9697499 times.
✓ Branch 1 taken 34412 times.
✓ Branch 2 taken 9697499 times.
✗ Branch 3 not taken.
9731911 in_data = !(peek_pos >= st->write_pos && peek_pos < st->read_pos);
125 }
126
127
2/2
✓ Branch 0 taken 18373496 times.
✓ Branch 1 taken 11273 times.
18384769 if (in_data) {
128 18373496 *res = buffer[peek_pos];
129 18373496 ret = CHANNEL_SUCCESS;
130
2/2
✓ Branch 1 taken 10649 times.
✓ Branch 2 taken 624 times.
11273 } else if (!buffered_more(chan)) {
131 10649 ret = CHANNEL_END;
132
1/2
✓ Branch 1 taken 624 times.
✗ Branch 2 not taken.
624 } else if (buffered_more(chan)) {
133 624 ret = CHANNEL_MORE;
134 }
135 18384769 mutex_unlock(&st->lock);
136 18384769 return ret;
137 }
138
139 4094051 bool buffered_channel_is_empty(lbm_char_channel_t *chan) {
140 4094051 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
141
2/2
✓ Branch 0 taken 10747 times.
✓ Branch 1 taken 4083304 times.
4094051 if (st->read_pos == st->write_pos) {
142 10747 return true;
143 }
144 4083304 return false;
145 }
146
147 3149039 bool buffered_channel_is_full(lbm_char_channel_t *chan) {
148 3149039 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
149
2/2
✓ Branch 0 taken 3128610 times.
✓ Branch 1 taken 20429 times.
3149039 if (st->write_pos == st->read_pos - 1 ||
150
2/2
✓ Branch 0 taken 1554769 times.
✓ Branch 1 taken 1573841 times.
3128610 (st->read_pos == 0 &&
151
2/2
✓ Branch 0 taken 7786 times.
✓ Branch 1 taken 1546983 times.
1554769 st->write_pos == TOKENIZER_BUFFER_SIZE-1)) {
152 28215 return true;
153 }
154 3120824 return false;
155 }
156
157 3120703 bool buffered_read(lbm_char_channel_t *chan, char *res) {
158 3120703 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
159 3120703 char *buffer = st->buffer;
160 3120703 bool ret = false;
161 3120703 mutex_lock(&st->lock);
162
1/2
✓ Branch 1 taken 3120703 times.
✗ Branch 2 not taken.
3120703 if (!buffered_channel_is_empty(chan)) {
163 3120703 *res = buffer[st->read_pos];
164 3120703 st->column++;
165
2/2
✓ Branch 0 taken 103422 times.
✓ Branch 1 taken 3017281 times.
3120703 if (*res == '\n') {
166 103422 st->column = 0;
167 103422 st->row ++;
168 }
169 3120703 st->read_pos = (st->read_pos + 1) % TOKENIZER_BUFFER_SIZE;
170 3120703 ret = true;
171 }
172 3120703 mutex_unlock(&st->lock);
173 3120703 return ret;
174 }
175
176 2020881 bool buffered_drop(lbm_char_channel_t *chan, unsigned int n) {
177 2020881 bool r = true;
178 char c;
179
180
2/2
✓ Branch 0 taken 3120703 times.
✓ Branch 1 taken 2020881 times.
5141584 for (unsigned int i = 0; i < n; i ++) {
181 3120703 r = buffered_read(chan, &c);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3120703 times.
3120703 if (r == false) break;
183 }
184 2020881 return r;
185 }
186
187 3149039 int buffered_write(lbm_char_channel_t *chan, char c) {
188 3149039 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3149039 times.
3149039 if (st->reader_closed) return CHANNEL_READER_CLOSED;
190 3149039 int ret = CHANNEL_FULL;
191 3149039 mutex_lock(&st->lock);
192 3149039 char *buffer = st->buffer;
193
2/2
✓ Branch 1 taken 3120824 times.
✓ Branch 2 taken 28215 times.
3149039 if (!buffered_channel_is_full(chan)) {
194 3120824 buffer[st->write_pos] = c;
195 3120824 st->write_pos = (st->write_pos + 1) % TOKENIZER_BUFFER_SIZE;
196 3120824 ret = CHANNEL_SUCCESS;
197 }
198 3149039 mutex_unlock(&st->lock);
199 3149039 return ret;
200 }
201
202 46998 unsigned int buffered_row(lbm_char_channel_t *chan) {
203 46998 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
204 46998 return st->row;
205 }
206
207 unsigned int buffered_column(lbm_char_channel_t *chan) {
208 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
209 return st->column;
210 }
211
212 900352 bool buffered_comment(lbm_char_channel_t *chan) {
213 900352 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
214 900352 return st->comment;
215 }
216
217 5487 void buffered_set_comment(lbm_char_channel_t *chan, bool comment) {
218 5487 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
219 5487 st->comment = comment;
220 5487 }
221
222 10752 void lbm_create_buffered_char_channel(lbm_buffered_channel_state_t *st,
223 lbm_char_channel_t *chan) {
224
225 10752 st->write_pos = 0;
226 10752 st->read_pos = 0;
227 10752 st->more = true;
228 10752 st->reader_closed = false;
229 10752 st->comment = false;
230 10752 st->row = 1;
231 10752 st->column = 1;
232
233
1/2
✓ Branch 0 taken 10752 times.
✗ Branch 1 not taken.
10752 if (!st->mutex_initialized) {
234 10752 mutex_init(&st->lock);
235 10752 st->mutex_initialized = true;
236 }
237
238 10752 chan->state = st;
239 10752 chan->more = buffered_more;
240 10752 chan->peek = buffered_peek;
241 10752 chan->read = buffered_read;
242 10752 chan->drop = buffered_drop;
243 10752 chan->comment = buffered_comment;
244 10752 chan->set_comment = buffered_set_comment;
245 10752 chan->channel_is_empty = buffered_channel_is_empty;
246 10752 chan->channel_is_full = buffered_channel_is_full;
247 10752 chan->write = buffered_write;
248 10752 chan->writer_close = buffered_writer_close;
249 10752 chan->reader_close = buffered_reader_close;
250 10752 chan->reader_is_closed = buffered_reader_is_closed;
251 10752 chan->row = buffered_row;
252 10752 chan->column = buffered_column;
253 10752 chan->may_block = buffered_may_block;
254 10752 }
255
256 /* ------------------------------------------------------------
257 Implementation string channel
258 ------------------------------------------------------------ */
259
260 15540 bool string_may_block(lbm_char_channel_t *chan) {
261 (void) chan;
262 15540 return false;
263 }
264
265 9590652 bool string_more(lbm_char_channel_t *chan) {
266 9590652 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
267 9590652 return st->more;
268 }
269
270 void string_writer_close(lbm_char_channel_t *chan) {
271 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
272 st->more = false;
273 }
274
275 319477 void string_reader_close(lbm_char_channel_t *chan) {
276 319477 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
277 319477 st->reader_closed = true;
278 319477 }
279
280 bool string_reader_is_closed(lbm_char_channel_t *chan) {
281 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
282 return st->reader_closed;
283 }
284
285 126859020 int string_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
286 126859020 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
287 126859020 char *str = st->str;
288
289 126859020 unsigned int peek_pos = st->read_pos + n;
290
291
2/2
✓ Branch 0 taken 126836021 times.
✓ Branch 1 taken 22999 times.
126859020 if (peek_pos < st->length) {
292 126836021 *res = str[peek_pos];
293 126836021 return CHANNEL_SUCCESS;
294 }
295 22999 return CHANNEL_END;
296 }
297
298 9590652 bool string_channel_is_empty(lbm_char_channel_t *chan) {
299 9590652 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
300
2/2
✓ Branch 0 taken 22425 times.
✓ Branch 1 taken 9568227 times.
9590652 if (st->read_pos == st->length) {
301 22425 return true;
302 }
303 9568227 return false;
304 }
305
306 bool string_channel_is_full(lbm_char_channel_t *chan) {
307 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
308 if (st->write_pos == st->length) {
309 return true;
310 }
311 return false;
312 }
313
314 10495489 bool string_read(lbm_char_channel_t *chan, char *res) {
315 10495489 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
316 10495489 char *str = st->str;
317
318
1/2
✓ Branch 0 taken 10495489 times.
✗ Branch 1 not taken.
10495489 if (st->read_pos < st->length) {
319 10495489 *res = str[st->read_pos];
320
2/2
✓ Branch 0 taken 103429 times.
✓ Branch 1 taken 10392060 times.
10495489 if (*res == '\n') {
321 103429 st->row ++;
322 103429 st->column = 1;
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10392060 times.
10392060 } else if (*res == 0) {
324 st->more = false;
325 } else {
326 10392060 st->column++;
327 }
328 10495489 st->read_pos = st->read_pos + 1;
329 } else {
330 st->more = false;
331 }
332 10495489 return true;
333 }
334
335 8824631 bool string_drop(lbm_char_channel_t *chan, unsigned int n) {
336 8824631 bool r = true;
337 char c;
338
339
1/2
✓ Branch 0 taken 8824631 times.
✗ Branch 1 not taken.
8824631 if (n > 0) {
340 do {
341 10495489 r = string_read(chan, &c);
342 10495489 n--;
343
3/4
✓ Branch 0 taken 1670858 times.
✓ Branch 1 taken 8824631 times.
✓ Branch 2 taken 1670858 times.
✗ Branch 3 not taken.
10495489 } while (n > 0 && r);
344 }
345 8824631 return r;
346 }
347
348 137962 int string_write(lbm_char_channel_t *chan, char c) {
349 137962 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
350 137962 char *str = st->str;
351
352
2/2
✓ Branch 0 taken 59008 times.
✓ Branch 1 taken 78954 times.
137962 if (st->write_pos < st->length - 1) {
353 59008 str[st->write_pos] = c;
354 59008 st->write_pos = st->write_pos + 1;
355 } else {
356 78954 return CHANNEL_FULL;
357 }
358 59008 return CHANNEL_SUCCESS;
359 }
360
361 400806 unsigned int string_row(lbm_char_channel_t *chan) {
362 400806 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
363 400806 return st->row;
364 }
365
366 unsigned int string_column(lbm_char_channel_t *chan) {
367 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
368 return st->column;
369 }
370
371 4792183 bool string_comment(lbm_char_channel_t *chan) {
372 4792183 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
373 4792183 return st->comment;
374 }
375
376 5488 void string_set_comment(lbm_char_channel_t *chan, bool comment) {
377 5488 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
378 5488 st->comment = comment;
379 5488 }
380
381 319480 void lbm_create_string_char_channel(lbm_string_channel_state_t *st,
382 lbm_char_channel_t *chan,
383 char *str) {
384
385 319480 st->str = str;
386 319480 st->length = (unsigned int)strlen(str);
387 319480 st->read_pos = 0;
388 319480 st->write_pos = 0;
389 319480 st->more = false;
390 319480 st->comment = false;
391 319480 st->row = 1;
392 319480 st->column = 1;
393
394 319480 chan->dependency = ENC_SYM_NIL;
395 319480 chan->state = st;
396 319480 chan->more = string_more;
397 319480 chan->peek = string_peek;
398 319480 chan->read = string_read;
399 319480 chan->drop = string_drop;
400 319480 chan->comment = string_comment;
401 319480 chan->set_comment = string_set_comment;
402 319480 chan->channel_is_empty = string_channel_is_empty;
403 319480 chan->channel_is_full = string_channel_is_full;
404 319480 chan->write = string_write;
405 319480 chan->writer_close = string_writer_close;
406 319480 chan->reader_close = string_reader_close;
407 319480 chan->reader_is_closed = string_reader_is_closed;
408 319480 chan->row = string_row;
409 319480 chan->column = string_column;
410 319480 chan->may_block = string_may_block;
411 319480 }
412
413 45140 void lbm_create_string_char_channel_size(lbm_string_channel_state_t *st,
414 lbm_char_channel_t *chan,
415 char *str,
416 unsigned int size) {
417 45140 st->str = str;
418 45140 st->length = size;
419 45140 st->read_pos = 0;
420 45140 st->write_pos = 0;
421 45140 st->more = false;
422 45140 st->comment = false;
423 45140 st->row = 1;
424 45140 st->column = 1;
425
426 45140 chan->dependency = ENC_SYM_NIL;
427 45140 chan->state = st;
428 45140 chan->more = string_more;
429 45140 chan->peek = string_peek;
430 45140 chan->read = string_read;
431 45140 chan->drop = string_drop;
432 45140 chan->comment = string_comment;
433 45140 chan->set_comment = string_set_comment;
434 45140 chan->channel_is_empty = string_channel_is_empty;
435 45140 chan->channel_is_full = string_channel_is_full;
436 45140 chan->write = string_write;
437 45140 chan->writer_close = string_writer_close;
438 45140 chan->reader_close = string_reader_close;
439 45140 chan->reader_is_closed = string_reader_is_closed;
440 45140 chan->row = string_row;
441 45140 chan->column = string_column;
442 45140 chan->may_block = string_may_block;
443 45140 }
444
445 308728 void lbm_char_channel_set_dependency(lbm_char_channel_t *chan, lbm_value dep) {
446 308728 chan->dependency = dep;
447 308728 }
448
449