GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/lbm_channel.c Lines: 255 285 89.5 %
Date: 2025-01-19 11:10:47 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
11382587
bool lbm_channel_more(lbm_char_channel_t *chan) {
26
11382587
  return chan->more(chan);
27
}
28
29
145205439
int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
30
145205439
  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
10857714
bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) {
38
10857714
  return chan->drop(chan, n);
39
}
40
41
5691466
bool lbm_channel_comment(lbm_char_channel_t *chan) {
42
5691466
  return chan->comment(chan);
43
}
44
45
11590
void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) {
46
11590
  chan->set_comment(chan, comment);
47
11590
}
48
49
10563178
bool lbm_channel_is_empty(lbm_char_channel_t *chan) {
50
10563178
  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
5305995
int lbm_channel_write(lbm_char_channel_t *chan, char c) {
58
5305995
  return chan->write(chan, c);
59
}
60
61
10794
void lbm_channel_writer_close(lbm_char_channel_t *chan) {
62
10794
  chan->writer_close(chan);
63
10794
}
64
65
330281
void lbm_channel_reader_close(lbm_char_channel_t *chan) {
66
330281
  chan->reader_close(chan);
67
330281
}
68
69
bool lbm_channel_reader_is_closed(lbm_char_channel_t *chan) {
70
  return chan->reader_is_closed(chan);
71
}
72
73
377897
unsigned int lbm_channel_row(lbm_char_channel_t *chan) {
74
377897
  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
26348
bool lbm_channel_may_block(lbm_char_channel_t *chan) {
82
26348
  return chan->may_block(chan);
83
}
84
85
/* ------------------------------------------------------------
86
   Implementation buffered channel
87
   ------------------------------------------------------------ */
88
10794
bool buffered_may_block(lbm_char_channel_t *chan) {
89
  (void) chan;
90
10794
  return true;
91
}
92
93
1806006
bool buffered_more(lbm_char_channel_t *chan) {
94
1806006
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
95
1806006
  return st->more;
96
}
97
98
10794
void buffered_writer_close(lbm_char_channel_t *chan) {
99
10794
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
100
10794
  st->more = false;
101
10794
}
102
103
10789
void buffered_reader_close(lbm_char_channel_t *chan) {
104
10789
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
105
10789
  st->reader_closed = true;
106
10789
}
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
18371099
int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
114
18371099
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
115
18371099
  char *buffer = st->buffer;
116
18371099
  int ret = CHANNEL_MORE;
117
18371099
  mutex_lock(&st->lock);
118
18371099
  unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE;
119
  bool in_data;
120
121
18371099
  if (st->write_pos >= st->read_pos) {
122

8551050
    in_data = peek_pos < st->write_pos && peek_pos >= st->read_pos;
123
  } else {
124

9820049
    in_data = !(peek_pos >= st->write_pos && peek_pos < st->read_pos);
125
  }
126
127
18371099
  if (in_data) {
128
18359767
    *res = buffer[peek_pos];
129
18359767
    ret = CHANNEL_SUCCESS;
130
11332
  } else if (!buffered_more(chan)) {
131
10691
    ret = CHANNEL_END;
132
641
  } else if (buffered_more(chan)) {
133
641
    ret = CHANNEL_MORE;
134
  }
135
18371099
  mutex_unlock(&st->lock);
136
18371099
  return ret;
137
}
138
139
4102506
bool buffered_channel_is_empty(lbm_char_channel_t *chan) {
140
4102506
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
141
4102506
  if (st->read_pos == st->write_pos) {
142
10789
    return true;
143
  }
144
4091717
  return false;
145
}
146
147
3158317
bool buffered_channel_is_full(lbm_char_channel_t *chan) {
148
3158317
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
149
3158317
  if (st->write_pos == st->read_pos - 1 ||
150
3136001
      (st->read_pos == 0 &&
151
1557443
       st->write_pos == TOKENIZER_BUFFER_SIZE-1)) {
152
30255
    return true;
153
  }
154
3128062
  return false;
155
}
156
157
3127882
bool buffered_read(lbm_char_channel_t *chan, char *res) {
158
3127882
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
159
3127882
  char *buffer = st->buffer;
160
3127882
  bool ret = false;
161
3127882
  mutex_lock(&st->lock);
162
3127882
  if (!buffered_channel_is_empty(chan)) {
163
3127882
    *res = buffer[st->read_pos];
164
3127882
    st->column++;
165
3127882
    if (*res == '\n') {
166
103691
      st->column = 0;
167
103691
      st->row ++;
168
    }
169
3127882
    st->read_pos = (st->read_pos + 1) % TOKENIZER_BUFFER_SIZE;
170
3127882
    ret = true;
171
  }
172
3127882
  mutex_unlock(&st->lock);
173
3127882
  return ret;
174
}
175
176
2027440
bool buffered_drop(lbm_char_channel_t *chan, unsigned int n) {
177
2027440
  bool r = true;
178
  char c;
179
180
5155322
  for (unsigned int i = 0; i < n; i ++) {
181
3127882
    r = buffered_read(chan, &c);
182
3127882
    if (r == false) break;
183
  }
184
2027440
  return r;
185
}
186
187
3158317
int buffered_write(lbm_char_channel_t *chan, char c) {
188
3158317
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
189
3158317
  if (st->reader_closed) return CHANNEL_READER_CLOSED;
190
3158317
  int ret = CHANNEL_FULL;
191
3158317
  mutex_lock(&st->lock);
192
3158317
  char *buffer = st->buffer;
193
3158317
  if (!buffered_channel_is_full(chan)) {
194
3128062
    buffer[st->write_pos] = c;
195
3128062
    st->write_pos = (st->write_pos + 1) % TOKENIZER_BUFFER_SIZE;
196
3128062
    ret = CHANNEL_SUCCESS;
197
  }
198
3158317
  mutex_unlock(&st->lock);
199
3158317
  return ret;
200
}
201
202
46916
unsigned int buffered_row(lbm_char_channel_t *chan) {
203
46916
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
204
46916
  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
900178
bool buffered_comment(lbm_char_channel_t *chan) {
213
900178
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
214
900178
  return st->comment;
215
}
216
217
5794
void buffered_set_comment(lbm_char_channel_t *chan, bool comment) {
218
5794
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
219
5794
  st->comment = comment;
220
5794
}
221
222
10794
void lbm_create_buffered_char_channel(lbm_buffered_channel_state_t *st,
223
                                      lbm_char_channel_t *chan) {
224
225
10794
  st->write_pos = 0;
226
10794
  st->read_pos = 0;
227
10794
  st->more = true;
228
10794
  st->reader_closed = false;
229
10794
  st->comment = false;
230
10794
  st->row = 1;
231
10794
  st->column = 1;
232
233
10794
  if (!st->mutex_initialized) {
234
10794
    mutex_init(&st->lock);
235
10794
    st->mutex_initialized = true;
236
  }
237
238
10794
  chan->state = st;
239
10794
  chan->more = buffered_more;
240
10794
  chan->peek = buffered_peek;
241
10794
  chan->read = buffered_read;
242
10794
  chan->drop = buffered_drop;
243
10794
  chan->comment = buffered_comment;
244
10794
  chan->set_comment = buffered_set_comment;
245
10794
  chan->channel_is_empty = buffered_channel_is_empty;
246
10794
  chan->channel_is_full = buffered_channel_is_full;
247
10794
  chan->write = buffered_write;
248
10794
  chan->writer_close = buffered_writer_close;
249
10794
  chan->reader_close = buffered_reader_close;
250
10794
  chan->reader_is_closed = buffered_reader_is_closed;
251
10794
  chan->row = buffered_row;
252
10794
  chan->column = buffered_column;
253
10794
  chan->may_block = buffered_may_block;
254
10794
}
255
256
/* ------------------------------------------------------------
257
   Implementation string channel
258
   ------------------------------------------------------------ */
259
260
15554
bool string_may_block(lbm_char_channel_t *chan) {
261
  (void) chan;
262
15554
  return false;
263
}
264
265
9588554
bool string_more(lbm_char_channel_t *chan) {
266
9588554
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
267
9588554
  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
319492
void string_reader_close(lbm_char_channel_t *chan) {
276
319492
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
277
319492
  st->reader_closed = true;
278
319492
}
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
126834340
int string_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
286
126834340
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
287
126834340
  char *str = st->str;
288
289
126834340
  unsigned int peek_pos = st->read_pos + n;
290
291
126834340
  if (peek_pos < st->length) {
292
126811298
    *res = str[peek_pos];
293
126811298
    return CHANNEL_SUCCESS;
294
  }
295
23042
  return CHANNEL_END;
296
}
297
298
9588554
bool string_channel_is_empty(lbm_char_channel_t *chan) {
299
9588554
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
300
9588554
  if (st->read_pos == st->length) {
301
22468
    return true;
302
  }
303
9566086
  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
10500600
bool string_read(lbm_char_channel_t *chan, char *res) {
315
10500600
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
316
10500600
  char *str = st->str;
317
318
10500600
  if (st->read_pos < st->length) {
319
10500600
    *res = str[st->read_pos];
320
10500600
    if (*res == '\n') {
321
103696
      st->row ++;
322
103696
      st->column = 1;
323
10396904
    } else if (*res == 0) {
324
      st->more = false;
325
    } else {
326
10396904
      st->column++;
327
    }
328
10500600
    st->read_pos = st->read_pos + 1;
329
  } else {
330
    st->more = false;
331
  }
332
10500600
  return true;
333
}
334
335
8830274
bool string_drop(lbm_char_channel_t *chan, unsigned int n) {
336
8830274
  bool r = true;
337
  char c;
338
339
8830274
  if (n > 0) {
340
    do {
341
10500600
      r = string_read(chan, &c);
342
10500600
      n--;
343

10500600
    } while (n > 0 && r);
344
  }
345
8830274
  return r;
346
}
347
348
2152217
int string_write(lbm_char_channel_t *chan, char c) {
349
2152217
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
350
2152217
  char *str = st->str;
351
352
2152217
  if (st->write_pos < st->length - 1) {
353
1905431
    str[st->write_pos] = c;
354
1905431
    st->write_pos = st->write_pos + 1;
355
  } else {
356
246786
    return CHANNEL_FULL;
357
  }
358
1905431
  return CHANNEL_SUCCESS;
359
}
360
361
400701
unsigned int string_row(lbm_char_channel_t *chan) {
362
400701
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
363
400701
  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
4791288
bool string_comment(lbm_char_channel_t *chan) {
372
4791288
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
373
4791288
  return st->comment;
374
}
375
376
5796
void string_set_comment(lbm_char_channel_t *chan, bool comment) {
377
5796
  lbm_string_channel_state_t *st = (lbm_string_channel_state_t*)chan->state;
378
5796
  st->comment = comment;
379
5796
}
380
381
319494
void lbm_create_string_char_channel(lbm_string_channel_state_t *st,
382
                                    lbm_char_channel_t *chan,
383
                                    char *str) {
384
385
319494
  st->str = str;
386
319494
  st->length = (unsigned int)strlen(str);
387
319494
  st->read_pos = 0;
388
319494
  st->write_pos = 0;
389
319494
  st->more = false;
390
319494
  st->comment = false;
391
319494
  st->row = 1;
392
319494
  st->column = 1;
393
394
319494
  chan->dependency = ENC_SYM_NIL;
395
319494
  chan->state = st;
396
319494
  chan->more = string_more;
397
319494
  chan->peek = string_peek;
398
319494
  chan->read = string_read;
399
319494
  chan->drop = string_drop;
400
319494
  chan->comment = string_comment;
401
319494
  chan->set_comment = string_set_comment;
402
319494
  chan->channel_is_empty = string_channel_is_empty;
403
319494
  chan->channel_is_full = string_channel_is_full;
404
319494
  chan->write = string_write;
405
319494
  chan->writer_close = string_writer_close;
406
319494
  chan->reader_close = string_reader_close;
407
319494
  chan->reader_is_closed = string_reader_is_closed;
408
319494
  chan->row = string_row;
409
319494
  chan->column = string_column;
410
319494
  chan->may_block = string_may_block;
411
319494
}
412
413
328843
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
328843
  st->str = str;
418
328843
  st->length = size;
419
328843
  st->read_pos = 0;
420
328843
  st->write_pos = 0;
421
328843
  st->more = false;
422
328843
  st->comment = false;
423
328843
  st->row = 1;
424
328843
  st->column = 1;
425
426
328843
  chan->dependency = ENC_SYM_NIL;
427
328843
  chan->state = st;
428
328843
  chan->more = string_more;
429
328843
  chan->peek = string_peek;
430
328843
  chan->read = string_read;
431
328843
  chan->drop = string_drop;
432
328843
  chan->comment = string_comment;
433
328843
  chan->set_comment = string_set_comment;
434
328843
  chan->channel_is_empty = string_channel_is_empty;
435
328843
  chan->channel_is_full = string_channel_is_full;
436
328843
  chan->write = string_write;
437
328843
  chan->writer_close = string_writer_close;
438
328843
  chan->reader_close = string_reader_close;
439
328843
  chan->reader_is_closed = string_reader_is_closed;
440
328843
  chan->row = string_row;
441
328843
  chan->column = string_column;
442
328843
  chan->may_block = string_may_block;
443
328843
}
444
445
308700
void lbm_char_channel_set_dependency(lbm_char_channel_t *chan, lbm_value dep) {
446
308700
  chan->dependency = dep;
447
308700
}
448