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-05 14:36:58 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
11399495
bool lbm_channel_more(lbm_char_channel_t *chan) {
26
11399495
  return chan->more(chan);
27
}
28
29
145345164
int lbm_channel_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
30
145345164
  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
10857479
bool lbm_channel_drop(lbm_char_channel_t *chan, unsigned int n) {
38
10857479
  return chan->drop(chan, n);
39
}
40
41
5699648
bool lbm_channel_comment(lbm_char_channel_t *chan) {
42
5699648
  return chan->comment(chan);
43
}
44
45
10969
void lbm_channel_set_comment(lbm_char_channel_t *chan, bool comment) {
46
10969
  chan->set_comment(chan, comment);
47
10969
}
48
49
10554196
bool lbm_channel_is_empty(lbm_char_channel_t *chan) {
50
10554196
  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
3292077
int lbm_channel_write(lbm_char_channel_t *chan, char c) {
58
3292077
  return chan->write(chan, c);
59
}
60
61
10836
void lbm_channel_writer_close(lbm_char_channel_t *chan) {
62
10836
  chan->writer_close(chan);
63
10836
}
64
65
330417
void lbm_channel_reader_close(lbm_char_channel_t *chan) {
66
330417
  chan->reader_close(chan);
67
330417
}
68
69
bool lbm_channel_reader_is_closed(lbm_char_channel_t *chan) {
70
  return chan->reader_is_closed(chan);
71
}
72
73
378344
unsigned int lbm_channel_row(lbm_char_channel_t *chan) {
74
378344
  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
26488
bool lbm_channel_may_block(lbm_char_channel_t *chan) {
82
26488
  return chan->may_block(chan);
83
}
84
85
/* ------------------------------------------------------------
86
   Implementation buffered channel
87
   ------------------------------------------------------------ */
88
10836
bool buffered_may_block(lbm_char_channel_t *chan) {
89
  (void) chan;
90
10836
  return true;
91
}
92
93
1813256
bool buffered_more(lbm_char_channel_t *chan) {
94
1813256
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
95
1813256
  return st->more;
96
}
97
98
10836
void buffered_writer_close(lbm_char_channel_t *chan) {
99
10836
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
100
10836
  st->more = false;
101
10836
}
102
103
10827
void buffered_reader_close(lbm_char_channel_t *chan) {
104
10827
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
105
10827
  st->reader_closed = true;
106
10827
}
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
18429974
int buffered_peek(lbm_char_channel_t *chan, unsigned int n, char *res) {
114
18429974
  lbm_buffered_channel_state_t *st = (lbm_buffered_channel_state_t*)chan->state;
115
18429974
  char *buffer = st->buffer;
116
18429974
  int ret = CHANNEL_MORE;
117
18429974
  mutex_lock(&st->lock);
118
18429974
  unsigned int peek_pos = (st->read_pos + n) % TOKENIZER_BUFFER_SIZE;
119
  bool in_data;
120
121
18429974
  if (st->write_pos >= st->read_pos) {
122

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

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

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