GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_channel.c
Date: 2024-08-06 17:32:21
Exec Total Coverage
Lines: 241 272 88.6%
Functions: 35 45 77.8%
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
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