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

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

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

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