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

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

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

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