GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_channel.c
Date: 2025-10-27 19:12:55
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 13102724 bool lbm_channel_more(lbm_char_channel_t *chan) {
26 13102724 return chan->more(chan);
27 }
28
29 169028032 int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
30 169028032 return chan->peek(chan, n, res);
31 }
32
33 189 bool lbm_channel_read(lbm_char_channel_t *chan, char *res) {
34 189 return chan->read(chan, res);
35 }
36
37 12769812 bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) {
38 12769812 return chan->drop(chan, n);
39 }
40
41 6557381 bool lbm_channel_comment(lbm_char_channel_t *chan) {
42 6557381 return chan->comment(chan);
43 }
44
45 25138 void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) {
46 25138 chan->set_comment(chan, comment);
47 25138 }
48
49 12224179 bool lbm_channel_is_empty(lbm_char_channel_t *chan) {
50 12224179 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 5497856 int lbm_channel_write(lbm_char_channel_t *chan, char c) {
58 5497856 return chan->write(chan, c);
59 }
60
61 11020 void lbm_channel_writer_close(lbm_char_channel_t *chan) {
62 11020 chan->writer_close(chan);
63 11020 }
64
65 334201 void lbm_channel_reader_close(lbm_char_channel_t *chan) {
66 334201 chan->reader_close(chan);
67 334201 }
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 413262 unsigned int lbm_channel_row(lbm_char_channel_t *chan) {
74 413262 return chan->row(chan);
75 }
76
77 117 unsigned int lbm_channel_column(lbm_char_channel_t *chan) {
78 117 return chan->column(chan);
79 }
80
81 28115 bool lbm_channel_may_block(lbm_char_channel_t *chan) {
82 28115 return chan->may_block(chan);
83 }
84
85 /* ------------------------------------------------------------
86 Implementation buffered channel
87 ------------------------------------------------------------ */
88 11019 bool buffered_may_block(lbm_char_channel_t *chan) {
89 (void) chan;
90 11019 return true;
91 }
92
93 1880002 bool buffered_more(lbm_char_channel_t *chan) {
94 1880002 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
95 1880002 return st->more;
96 }
97
98 11019 void buffered_writer_close(lbm_char_channel_t *chan) {
99 11019 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
100 11019 st->more = false;
101 11019 }
102
103 11007 void buffered_reader_close(lbm_char_channel_t *chan) {
104 11007 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
105 11007 st->reader_closed = true;
106 11007 }
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 20057201 int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
114 20057201 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
115 20057201 char *buffer = st->buffer;
116 20057201 int ret = CHANNEL_MORE;
117 20057201 lbm_mutex_lock(&st->lock);
118 20057201 unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE;
119 bool in_data;
120
121
2/2
✓ Branch 0 taken 9394090 times.
✓ Branch 1 taken 10663111 times.
20057201 if (st->write_pos >= st->read_pos) {
122
3/4
✓ Branch 0 taken 9381971 times.
✓ Branch 1 taken 12119 times.
✓ Branch 2 taken 9381971 times.
✗ Branch 3 not taken.
9394090 in_data = peek_pos < st->write_pos && peek_pos >= st->read_pos;
123 } else {
124
4/4
✓ Branch 0 taken 10627086 times.
✓ Branch 1 taken 36025 times.
✓ Branch 2 taken 10627083 times.
✓ Branch 3 taken 3 times.
10663111 in_data = !(peek_pos >= st->write_pos && peek_pos < st->read_pos);
125 }
126
127
2/2
✓ Branch 0 taken 20045079 times.
✓ Branch 1 taken 12122 times.
20057201 if (in_data) {
128 20045079 *res = buffer[peek_pos];
129 20045079 ret = CHANNEL_SUCCESS;
130
2/2
✓ Branch 0 taken 10894 times.
✓ Branch 1 taken 1228 times.
12122 } else if (!buffered_more(chan)) {
131 10894 ret = CHANNEL_END;
132
1/2
✓ Branch 0 taken 1228 times.
✗ Branch 1 not taken.
1228 } else if (buffered_more(chan)) {
133 1228 ret = CHANNEL_MORE;
134 }
135 20057201 lbm_mutex_unlock(&st->lock);
136 20057201 return ret;
137 }
138
139 4232020 bool buffered_channel_is_empty(lbm_char_channel_t *chan) {
140 4232020 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
141
2/2
✓ Branch 0 taken 11074 times.
✓ Branch 1 taken 4220946 times.
4232020 if (st->read_pos == st->write_pos) {
142 11074 return true;
143 }
144 4220946 return false;
145 }
146
147 3277890 bool buffered_channel_is_full(lbm_char_channel_t *chan) {
148 3277890 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
149
2/2
✓ Branch 0 taken 3254048 times.
✓ Branch 1 taken 23842 times.
3277890 if (st->write_pos == st->read_pos - 1 ||
150
2/2
✓ Branch 0 taken 1617452 times.
✓ Branch 1 taken 1636596 times.
3254048 (st->read_pos == 0 &&
151
2/2
✓ Branch 0 taken 9227 times.
✓ Branch 1 taken 1608225 times.
1617452 st->write_pos == TOKENIZER_BUFFER_SIZE-1)) {
152 33069 return true;
153 }
154 3244821 return false;
155 }
156
157 3243913 bool buffered_read(lbm_char_channel_t *chan, char *res) {
158 3243913 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
159 3243913 char *buffer = st->buffer;
160 3243913 bool ret = false;
161 3243913 lbm_mutex_lock(&st->lock);
162
2/2
✓ Branch 0 taken 3243847 times.
✓ Branch 1 taken 66 times.
3243913 if (!buffered_channel_is_empty(chan)) {
163 3243847 *res = buffer[st->read_pos];
164 3243847 st->column++;
165
2/2
✓ Branch 0 taken 106893 times.
✓ Branch 1 taken 3136954 times.
3243847 if (*res == '\n') {
166 106893 st->column = 1;
167 106893 st->row ++;
168 }
169 3243847 st->read_pos = (st->read_pos + 1) % TOKENIZER_BUFFER_SIZE;
170 3243847 ret = true;
171 }
172 3243913 lbm_mutex_unlock(&st->lock);
173 3243913 return ret;
174 }
175
176 2102044 bool buffered_drop(lbm_char_channel_t *chan, unsigned int n) {
177 2102044 bool r = true;
178 char c;
179
180
2/2
✓ Branch 0 taken 3243764 times.
✓ Branch 1 taken 2102044 times.
5345808 for (unsigned int i = 0; i < n; i ++) {
181 3243764 r = buffered_read(chan, &c);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3243764 times.
3243764 if (r == false) break;
183 }
184 2102044 return r;
185 }
186
187 3277633 int buffered_write(lbm_char_channel_t *chan, char c) {
188 3277633 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3277633 times.
3277633 if (st->reader_closed) return CHANNEL_READER_CLOSED;
190 3277633 int ret = CHANNEL_FULL;
191 3277633 lbm_mutex_lock(&st->lock);
192 3277633 char *buffer = st->buffer;
193
2/2
✓ Branch 0 taken 3244565 times.
✓ Branch 1 taken 33068 times.
3277633 if (!buffered_channel_is_full(chan)) {
194 3244565 buffer[st->write_pos] = c;
195 3244565 st->write_pos = (st->write_pos + 1) % TOKENIZER_BUFFER_SIZE;
196 3244565 ret = CHANNEL_SUCCESS;
197 }
198 3277633 lbm_mutex_unlock(&st->lock);
199 3277633 return ret;
200 }
201
202 47763 unsigned int buffered_row(lbm_char_channel_t *chan) {
203 47763 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
204 47763 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 936807 bool buffered_comment(lbm_char_channel_t *chan) {
213 936807 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
214 936807 return st->comment;
215 }
216
217 6098 void buffered_set_comment(lbm_char_channel_t *chan, bool comment) {
218 6098 lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
219 6098 st->comment = comment;
220 6098 }
221
222 11032 void lbm_create_buffered_char_channel(lbm_buffered_channel_state_t *st,
223 lbm_char_channel_t *chan) {
224
225 11032 st->write_pos = 0;
226 11032 st->read_pos = 0;
227 11032 st->more = true;
228 11032 st->reader_closed = false;
229 11032 st->comment = false;
230 11032 st->row = 1;
231 11032 st->column = 1;
232
233
2/2
✓ Branch 0 taken 11020 times.
✓ Branch 1 taken 12 times.
11032 if (!st->mutex_initialized) {
234 11020 lbm_mutex_init(&st->lock);
235 11020 st->mutex_initialized = true;
236 }
237
238 11032 chan->state = st;
239 11032 chan->more = buffered_more;
240 11032 chan->peek = buffered_peek;
241 11032 chan->read = buffered_read;
242 11032 chan->drop = buffered_drop;
243 11032 chan->comment = buffered_comment;
244 11032 chan->set_comment = buffered_set_comment;
245 11032 chan->channel_is_empty = buffered_channel_is_empty;
246 11032 chan->channel_is_full = buffered_channel_is_full;
247 11032 chan->write = buffered_write;
248 11032 chan->writer_close = buffered_writer_close;
249 11032 chan->reader_close = buffered_reader_close;
250 11032 chan->reader_is_closed = buffered_reader_is_closed;
251 11032 chan->row = buffered_row;
252 11032 chan->column = buffered_column;
253 11032 chan->may_block = buffered_may_block;
254 11032 }
255
256 /* ------------------------------------------------------------
257 Implementation string channel
258 ------------------------------------------------------------ */
259
260 17096 bool string_may_block(lbm_char_channel_t *chan) {
261 (void) chan;
262 17096 return false;
263 }
264
265 11236072 bool string_more(lbm_char_channel_t *chan) {
266 11236072 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
267 11236072 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 323194 void string_reader_close(lbm_char_channel_t *chan) {
276 323194 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
277 323194 st->reader_closed = true;
278 323194 }
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 148970831 int string_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
286 148970831 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
287 148970831 char *str = st->str;
288
289 148970831 unsigned int peek_pos = st->read_pos + n;
290
291
2/2
✓ Branch 0 taken 148945242 times.
✓ Branch 1 taken 25589 times.
148970831 if (peek_pos < st->length) {
292 148945242 *res = str[peek_pos];
293 148945242 return CHANNEL_SUCCESS;
294 }
295 25589 return CHANNEL_END;
296 }
297
298 11236072 bool string_channel_is_empty(lbm_char_channel_t *chan) {
299 11236072 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
300
2/2
✓ Branch 0 taken 25089 times.
✓ Branch 1 taken 11210983 times.
11236072 if (st->read_pos == st->length) {
301 25089 return true;
302 }
303 11210983 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 13693179 bool string_read(lbm_char_channel_t *chan, char *res) {
315 13693179 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
316 13693179 char *str = st->str;
317
318
2/2
✓ Branch 0 taken 13693177 times.
✓ Branch 1 taken 2 times.
13693179 if (st->read_pos < st->length) {
319 13693177 *res = str[st->read_pos];
320
2/2
✓ Branch 0 taken 212055 times.
✓ Branch 1 taken 13481122 times.
13693177 if (*res == '\n') {
321 212055 st->row ++;
322 212055 st->column = 1;
323
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13481120 times.
13481122 } else if (*res == 0) {
324 2 st->more = false;
325 } else {
326 13481120 st->column++;
327 }
328 13693177 st->read_pos = st->read_pos + 1;
329 } else {
330 2 st->more = false;
331 }
332 13693179 return true;
333 }
334
335 10667768 bool string_drop(lbm_char_channel_t *chan, unsigned int n) {
336 10667768 bool r = true;
337 char c;
338
339
1/2
✓ Branch 0 taken 10667768 times.
✗ Branch 1 not taken.
10667768 if (n > 0) {
340 do {
341 13693139 r = string_read(chan, &c);
342 13693139 n--;
343
3/4
✓ Branch 0 taken 3025371 times.
✓ Branch 1 taken 10667768 times.
✓ Branch 2 taken 3025371 times.
✗ Branch 3 not taken.
13693139 } while (n > 0 && r);
344 }
345 10667768 return r;
346 }
347
348 2223835 int string_write(lbm_char_channel_t *chan, char c) {
349 2223835 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
350 2223835 char *str = st->str;
351
352
2/2
✓ Branch 0 taken 1969693 times.
✓ Branch 1 taken 254142 times.
2223835 if (st->write_pos < st->length) {
353 1969693 str[st->write_pos] = c;
354 1969693 st->write_pos = st->write_pos + 1;
355 } else {
356 254142 return CHANNEL_FULL;
357 }
358 1969693 return CHANNEL_SUCCESS;
359 }
360
361 469087 unsigned int string_row(lbm_char_channel_t *chan) {
362 469087 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
363 469087 return st->row;
364 }
365
366 116 unsigned int string_column(lbm_char_channel_t *chan) {
367 116 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
368 116 return st->column;
369 }
370
371 5620574 bool string_comment(lbm_char_channel_t *chan) {
372 5620574 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
373 5620574 return st->comment;
374 }
375
376 19040 void string_set_comment(lbm_char_channel_t *chan, bool comment) {
377 19040 lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
378 19040 st->comment = comment;
379 19040 }
380
381 324721 void lbm_create_string_char_channel(lbm_string_channel_state_t *st,
382 lbm_char_channel_t *chan,
383 char *str) {
384
385 324721 st->str = str;
386 324721 st->length = (unsigned int)strlen(str);
387 324721 st->read_pos = 0;
388 324721 st->write_pos = 0;
389 324721 st->more = false;
390 324721 st->comment = false;
391 324721 st->row = 1;
392 324721 st->column = 1;
393
394 324721 chan->dependency = ENC_SYM_NIL;
395 324721 chan->state = st;
396 324721 chan->more = string_more;
397 324721 chan->peek = string_peek;
398 324721 chan->read = string_read;
399 324721 chan->drop = string_drop;
400 324721 chan->comment = string_comment;
401 324721 chan->set_comment = string_set_comment;
402 324721 chan->channel_is_empty = string_channel_is_empty;
403 324721 chan->channel_is_full = string_channel_is_full;
404 324721 chan->write = string_write;
405 324721 chan->writer_close = string_writer_close;
406 324721 chan->reader_close = string_reader_close;
407 324721 chan->reader_is_closed = string_reader_is_closed;
408 324721 chan->row = string_row;
409 324721 chan->column = string_column;
410 324721 chan->may_block = string_may_block;
411 324721 }
412
413 336468 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 336468 st->str = str;
418 336468 st->length = size;
419 336468 st->read_pos = 0;
420 336468 st->write_pos = 0;
421 336468 st->more = false;
422 336468 st->comment = false;
423 336468 st->row = 1;
424 336468 st->column = 1;
425
426 336468 chan->dependency = ENC_SYM_NIL;
427 336468 chan->state = st;
428 336468 chan->more = string_more;
429 336468 chan->peek = string_peek;
430 336468 chan->read = string_read;
431 336468 chan->drop = string_drop;
432 336468 chan->comment = string_comment;
433 336468 chan->set_comment = string_set_comment;
434 336468 chan->channel_is_empty = string_channel_is_empty;
435 336468 chan->channel_is_full = string_channel_is_full;
436 336468 chan->write = string_write;
437 336468 chan->writer_close = string_writer_close;
438 336468 chan->reader_close = string_reader_close;
439 336468 chan->reader_is_closed = string_reader_is_closed;
440 336468 chan->row = string_row;
441 336468 chan->column = string_column;
442 336468 chan->may_block = string_may_block;
443 336468 }
444
445 311912 void lbm_char_channel_set_dependency(lbm_char_channel_t *chan, lbm_value dep) {
446 311912 chan->dependency = dep;
447 311912 }
448
449