GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_channel.c
Date: 2025-10-28 15:15:18
Exec Total Coverage
Lines: 286 286 100.0%
Functions: 49 49 100.0%
Branches: 52 58 89.7%

Line Branch Exec Source
1 /*
2 Copyright 2022, 2025 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 36274038 bool lbm_channel_more(lbm_char_channel_t *chan) {
26 36274038 return chan->more(chan);
27 }
28
29 480089941 int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
30 480089941 return chan->peek(chan, n, res);
31 }
32
33 190 bool lbm_channel_read(lbm_char_channel_t *chan, char *res) {
34 190 return chan->read(chan, res);
35 }
36
37 34875443 bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) {
38 34875443 return chan->drop(chan, n);
39 }
40
41 18144589 bool lbm_channel_comment(lbm_char_channel_t *chan) {
42 18144589 return chan->comment(chan);
43 }
44
45 49632 void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) {
46 49632 chan->set_comment(chan, comment);
47 49632 }
48
49 33601695 bool lbm_channel_is_empty(lbm_char_channel_t *chan) {
50 33601695 return chan->channel_is_empty(chan);
51 }
52
53 263 bool lbm_channel_is_full(lbm_char_channel_t *chan) {
54 263 return chan->channel_is_full(chan);
55 }
56
57 16701943 int lbm_channel_write(lbm_char_channel_t *chan, char c) {
58 16701943 return chan->write(chan, c);
59 }
60
61 33093 void lbm_channel_writer_close(lbm_char_channel_t *chan) {
62 33093 chan->writer_close(chan);
63 33093 }
64
65 997462 void lbm_channel_reader_close(lbm_char_channel_t *chan) {
66 997462 chan->reader_close(chan);
67 997462 }
68
69 3 bool lbm_channel_reader_is_closed(lbm_char_channel_t *chan) {
70 3 return chan->reader_is_closed(chan);
71 }
72
73 1173076 unsigned int lbm_channel_row(lbm_char_channel_t *chan) {
74 1173076 return chan->row(chan);
75 }
76
77 229 unsigned int lbm_channel_column(lbm_char_channel_t *chan) {
78 229 return chan->column(chan);
79 }
80
81 83310 bool lbm_channel_may_block(lbm_char_channel_t *chan) {
82 83310 return chan->may_block(chan);
83 }
84
85 /* ------------------------------------------------------------
86 Implementation buffered channel
87 ------------------------------------------------------------ */
88 33055 bool buffered_may_block(lbm_char_channel_t *chan) {
89 (void) chan;
90 33055 return true;
91 }
92
93 5641765 bool buffered_more(lbm_char_channel_t *chan) {
94 5641765 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
95 5641765 return st->more;
96 }
97
98 33092 void buffered_writer_close(lbm_char_channel_t *chan) {
99 33092 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
100 33092 st->more = false;
101 33092 }
102
103 33016 void buffered_reader_close(lbm_char_channel_t *chan) {
104 33016 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
105 33016 st->reader_closed = true;
106 33016 }
107
108 2 bool buffered_reader_is_closed(lbm_char_channel_t *chan) {
109 2 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
110 2 return st->reader_closed;
111 }
112
113 60174188 int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
114 60174188 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
115 60174188 char *buffer = st->buffer;
116 60174188 int ret = CHANNEL_MORE;
117 60174188 lbm_mutex_lock(&st->lock);
118 60174188 unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE;
119 bool in_data;
120
121
2/2
✓ Branch 0 taken 29417751 times.
✓ Branch 1 taken 30756437 times.
60174188 if (st->write_pos >= st->read_pos) {
122
3/4
✓ Branch 0 taken 29380800 times.
✓ Branch 1 taken 36951 times.
✓ Branch 2 taken 29380800 times.
✗ Branch 3 not taken.
29417751 in_data = peek_pos < st->write_pos && peek_pos >= st->read_pos;
123 } else {
124
4/4
✓ Branch 0 taken 30648358 times.
✓ Branch 1 taken 108079 times.
✓ Branch 2 taken 30648352 times.
✓ Branch 3 taken 6 times.
30756437 in_data = !(peek_pos >= st->write_pos && peek_pos < st->read_pos);
125 }
126
127
2/2
✓ Branch 0 taken 60137231 times.
✓ Branch 1 taken 36957 times.
60174188 if (in_data) {
128 60137231 *res = buffer[peek_pos];
129 60137231 ret = CHANNEL_SUCCESS;
130
2/2
✓ Branch 0 taken 32723 times.
✓ Branch 1 taken 4234 times.
36957 } else if (!buffered_more(chan)) {
131 32723 ret = CHANNEL_END;
132
1/2
✓ Branch 0 taken 4234 times.
✗ Branch 1 not taken.
4234 } else if (buffered_more(chan)) {
133 4234 ret = CHANNEL_MORE;
134 }
135 60174188 lbm_mutex_unlock(&st->lock);
136 60174188 return ret;
137 }
138
139 12659505 bool buffered_channel_is_empty(lbm_char_channel_t *chan) {
140 12659505 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
141
2/2
✓ Branch 0 taken 33083 times.
✓ Branch 1 taken 12626422 times.
12659505 if (st->read_pos == st->write_pos) {
142 33083 return true;
143 }
144 12626422 return false;
145 }
146
147 9826537 bool buffered_channel_is_full(lbm_char_channel_t *chan) {
148 9826537 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
149
2/2
✓ Branch 0 taken 9761025 times.
✓ Branch 1 taken 65512 times.
9826537 if (st->write_pos == st->read_pos - 1 ||
150
2/2
✓ Branch 0 taken 4850094 times.
✓ Branch 1 taken 4910931 times.
9761025 (st->read_pos == 0 &&
151
2/2
✓ Branch 0 taken 27627 times.
✓ Branch 1 taken 4822467 times.
4850094 st->write_pos == TOKENIZER_BUFFER_SIZE-1)) {
152 93139 return true;
153 }
154 9733398 return false;
155 }
156
157 9731274 bool buffered_read(lbm_char_channel_t *chan, char *res) {
158 9731274 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
159 9731274 char *buffer = st->buffer;
160 9731274 bool ret = false;
161 9731274 lbm_mutex_lock(&st->lock);
162
2/2
✓ Branch 0 taken 9731208 times.
✓ Branch 1 taken 66 times.
9731274 if (!buffered_channel_is_empty(chan)) {
163 9731208 *res = buffer[st->read_pos];
164 9731208 st->column++;
165
2/2
✓ Branch 0 taken 320652 times.
✓ Branch 1 taken 9410556 times.
9731208 if (*res == '\n') {
166 320652 st->column = 1;
167 320652 st->row ++;
168 }
169 9731208 st->read_pos = (st->read_pos + 1) % TOKENIZER_BUFFER_SIZE;
170 9731208 ret = true;
171 }
172 9731274 lbm_mutex_unlock(&st->lock);
173 9731274 return ret;
174 }
175
176 6305968 bool buffered_drop(lbm_char_channel_t *chan, unsigned int n) {
177 6305968 bool r = true;
178 char c;
179
180
2/2
✓ Branch 0 taken 9731124 times.
✓ Branch 1 taken 6305968 times.
16037092 for (unsigned int i = 0; i < n; i ++) {
181 9731124 r = buffered_read(chan, &c);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9731124 times.
9731124 if (r == false) break;
183 }
184 6305968 return r;
185 }
186
187 9826280 int buffered_write(lbm_char_channel_t *chan, char c) {
188 9826280 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9826280 times.
9826280 if (st->reader_closed) return CHANNEL_READER_CLOSED;
190 9826280 int ret = CHANNEL_FULL;
191 9826280 lbm_mutex_lock(&st->lock);
192 9826280 char *buffer = st->buffer;
193
2/2
✓ Branch 0 taken 9733142 times.
✓ Branch 1 taken 93138 times.
9826280 if (!buffered_channel_is_full(chan)) {
194 9733142 buffer[st->write_pos] = c;
195 9733142 st->write_pos = (st->write_pos + 1) % TOKENIZER_BUFFER_SIZE;
196 9733142 ret = CHANNEL_SUCCESS;
197 }
198 9826280 lbm_mutex_unlock(&st->lock);
199 9826280 return ret;
200 }
201
202 143287 unsigned int buffered_row(lbm_char_channel_t *chan) {
203 143287 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
204 143287 return st->row;
205 }
206
207 1 unsigned int buffered_column(lbm_char_channel_t *chan) {
208 1 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
209 1 return st->column;
210 }
211
212 2810963 bool buffered_comment(lbm_char_channel_t *chan) {
213 2810963 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
214 2810963 return st->comment;
215 }
216
217 18294 void buffered_set_comment(lbm_char_channel_t *chan, bool comment) {
218 18294 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
219 18294 st->comment = comment;
220 18294 }
221
222 33115 void lbm_create_buffered_char_channel(lbm_buffered_channel_state_t *st,
223 lbm_char_channel_t *chan) {
224
225 33115 st->write_pos = 0;
226 33115 st->read_pos = 0;
227 33115 st->more = true;
228 33115 st->reader_closed = false;
229 33115 st->comment = false;
230 33115 st->row = 1;
231 33115 st->column = 1;
232
233
2/2
✓ Branch 0 taken 33103 times.
✓ Branch 1 taken 12 times.
33115 if (!st->mutex_initialized) {
234 33103 lbm_mutex_init(&st->lock);
235 33103 st->mutex_initialized = true;
236 }
237
238 33115 chan->state = st;
239 33115 chan->more = buffered_more;
240 33115 chan->peek = buffered_peek;
241 33115 chan->read = buffered_read;
242 33115 chan->drop = buffered_drop;
243 33115 chan->comment = buffered_comment;
244 33115 chan->set_comment = buffered_set_comment;
245 33115 chan->channel_is_empty = buffered_channel_is_empty;
246 33115 chan->channel_is_full = buffered_channel_is_full;
247 33115 chan->write = buffered_write;
248 33115 chan->writer_close = buffered_writer_close;
249 33115 chan->reader_close = buffered_reader_close;
250 33115 chan->reader_is_closed = buffered_reader_is_closed;
251 33115 chan->row = buffered_row;
252 33115 chan->column = buffered_column;
253 33115 chan->may_block = buffered_may_block;
254 33115 }
255
256 /* ------------------------------------------------------------
257 Implementation string channel
258 ------------------------------------------------------------ */
259
260 50255 bool string_may_block(lbm_char_channel_t *chan) {
261 (void) chan;
262 50255 return false;
263 }
264
265 30673464 bool string_more(lbm_char_channel_t *chan) {
266 30673464 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
267 30673464 return st->more;
268 }
269
270 1 void string_writer_close(lbm_char_channel_t *chan) {
271 1 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
272 1 st->more = false;
273 1 }
274
275 964446 void string_reader_close(lbm_char_channel_t *chan) {
276 964446 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
277 964446 st->reader_closed = true;
278 964446 }
279
280 1 bool string_reader_is_closed(lbm_char_channel_t *chan) {
281 1 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
282 1 return st->reader_closed;
283 }
284
285 419915753 int string_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
286 419915753 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
287 419915753 char *str = st->str;
288
289 419915753 unsigned int peek_pos = st->read_pos + n;
290
291
2/2
✓ Branch 0 taken 419843647 times.
✓ Branch 1 taken 72106 times.
419915753 if (peek_pos < st->length) {
292 419843647 *res = str[peek_pos];
293 419843647 return CHANNEL_SUCCESS;
294 }
295 72106 return CHANNEL_END;
296 }
297
298 30673464 bool string_channel_is_empty(lbm_char_channel_t *chan) {
299 30673464 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
300
2/2
✓ Branch 0 taken 70485 times.
✓ Branch 1 taken 30602979 times.
30673464 if (st->read_pos == st->length) {
301 70485 return true;
302 }
303 30602979 return false;
304 }
305
306 6 bool string_channel_is_full(lbm_char_channel_t *chan) {
307 6 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
308
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (st->write_pos == st->length) {
309 1 return true;
310 }
311 5 return false;
312 }
313
314 35101762 bool string_read(lbm_char_channel_t *chan, char *res) {
315 35101762 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
316 35101762 char *str = st->str;
317
318
2/2
✓ Branch 0 taken 35101760 times.
✓ Branch 1 taken 2 times.
35101762 if (st->read_pos < st->length) {
319 35101760 *res = str[st->read_pos];
320
2/2
✓ Branch 0 taken 426348 times.
✓ Branch 1 taken 34675412 times.
35101760 if (*res == '\n') {
321 426348 st->row ++;
322 426348 st->column = 1;
323
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34675410 times.
34675412 } else if (*res == 0) {
324 2 st->more = false;
325 } else {
326 34675410 st->column++;
327 }
328 35101760 st->read_pos = st->read_pos + 1;
329 } else {
330 2 st->more = false;
331 }
332 35101762 return true;
333 }
334
335 28569475 bool string_drop(lbm_char_channel_t *chan, unsigned int n) {
336 28569475 bool r = true;
337 char c;
338
339
1/2
✓ Branch 0 taken 28569475 times.
✗ Branch 1 not taken.
28569475 if (n > 0) {
340 do {
341 35101722 r = string_read(chan, &c);
342 35101722 n--;
343
3/4
✓ Branch 0 taken 6532247 times.
✓ Branch 1 taken 28569475 times.
✓ Branch 2 taken 6532247 times.
✗ Branch 3 not taken.
35101722 } while (n > 0 && r);
344 }
345 28569475 return r;
346 }
347
348 6886950 int string_write(lbm_char_channel_t *chan, char c) {
349 6886950 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
350 6886950 char *str = st->str;
351
352
2/2
✓ Branch 0 taken 5875212 times.
✓ Branch 1 taken 1011738 times.
6886950 if (st->write_pos < st->length) {
353 5875212 str[st->write_pos] = c;
354 5875212 st->write_pos = st->write_pos + 1;
355 } else {
356 1011738 return CHANNEL_FULL;
357 }
358 5875212 return CHANNEL_SUCCESS;
359 }
360
361 1274384 unsigned int string_row(lbm_char_channel_t *chan) {
362 1274384 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
363 1274384 return st->row;
364 }
365
366 228 unsigned int string_column(lbm_char_channel_t *chan) {
367 228 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
368 228 return st->column;
369 }
370
371 15333626 bool string_comment(lbm_char_channel_t *chan) {
372 15333626 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
373 15333626 return st->comment;
374 }
375
376 31338 void string_set_comment(lbm_char_channel_t *chan, bool comment) {
377 31338 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
378 31338 st->comment = comment;
379 31338 }
380
381 968969 void lbm_create_string_char_channel(lbm_string_channel_state_t *st,
382 lbm_char_channel_t *chan,
383 char *str) {
384
385 968969 st->str = str;
386 968969 st->length = (unsigned int)strlen(str);
387 968969 st->read_pos = 0;
388 968969 st->write_pos = 0;
389 968969 st->more = false;
390 968969 st->comment = false;
391 968969 st->row = 1;
392 968969 st->column = 1;
393
394 968969 chan->dependency = ENC_SYM_NIL;
395 968969 chan->state = st;
396 968969 chan->more = string_more;
397 968969 chan->peek = string_peek;
398 968969 chan->read = string_read;
399 968969 chan->drop = string_drop;
400 968969 chan->comment = string_comment;
401 968969 chan->set_comment = string_set_comment;
402 968969 chan->channel_is_empty = string_channel_is_empty;
403 968969 chan->channel_is_full = string_channel_is_full;
404 968969 chan->write = string_write;
405 968969 chan->writer_close = string_writer_close;
406 968969 chan->reader_close = string_reader_close;
407 968969 chan->reader_is_closed = string_reader_is_closed;
408 968969 chan->row = string_row;
409 968969 chan->column = string_column;
410 968969 chan->may_block = string_may_block;
411 968969 }
412
413 1002347 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 1002347 st->str = str;
418 1002347 st->length = size;
419 1002347 st->read_pos = 0;
420 1002347 st->write_pos = 0;
421 1002347 st->more = false;
422 1002347 st->comment = false;
423 1002347 st->row = 1;
424 1002347 st->column = 1;
425
426 1002347 chan->dependency = ENC_SYM_NIL;
427 1002347 chan->state = st;
428 1002347 chan->more = string_more;
429 1002347 chan->peek = string_peek;
430 1002347 chan->read = string_read;
431 1002347 chan->drop = string_drop;
432 1002347 chan->comment = string_comment;
433 1002347 chan->set_comment = string_set_comment;
434 1002347 chan->channel_is_empty = string_channel_is_empty;
435 1002347 chan->channel_is_full = string_channel_is_full;
436 1002347 chan->write = string_write;
437 1002347 chan->writer_close = string_writer_close;
438 1002347 chan->reader_close = string_reader_close;
439 1002347 chan->reader_is_closed = string_reader_is_closed;
440 1002347 chan->row = string_row;
441 1002347 chan->column = string_column;
442 1002347 chan->may_block = string_may_block;
443 1002347 }
444
445 931225 void lbm_char_channel_set_dependency(lbm_char_channel_t *chan, lbm_value dep) {
446 931225 chan->dependency = dep;
447 931225 }
448
449