1 /* inputbuf.c */ 2 3 /* 4 Copyright (C) 2008 Micah Cowan 5 6 This file is part of GNU teseq. 7 8 GNU teseq is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 GNU teseq is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "teseq.h" 23 24 #include <errno.h> 25 #include <stdlib.h> 26 27 #include "inputbuf.h" 28 #include "ringbuf.h" 29 30 struct inputbuf 31 { 32 FILE *file; 33 int saving; 34 size_t count; 35 size_t saved_count; 36 struct ringbuf *rb; 37 struct ringbuf_reader *reader; 38 int err; 39 }; 40 41 struct inputbuf * inputbuf_new(FILE * f,size_t bufsz)42inputbuf_new (FILE * f, size_t bufsz) 43 { 44 struct inputbuf *ret = NULL; 45 struct ringbuf *rb = NULL; 46 struct ringbuf_reader *reader = NULL; 47 48 ret = malloc (sizeof *ret); 49 if (!ret) 50 goto cleanup; 51 rb = ringbuf_new (bufsz); 52 if (!rb) 53 goto cleanup; 54 reader = ringbuf_reader_new (rb); 55 if (!reader) 56 goto cleanup; 57 58 ret->rb = rb; 59 ret->reader = reader; 60 ret->file = f; 61 ret->saving = 0; 62 ret->count = 0; 63 ret->err = 0; 64 return ret; 65 66 cleanup: 67 free (ret); 68 free (rb); 69 free (reader); 70 return NULL; 71 } 72 73 void inputbuf_delete(struct inputbuf * ib)74inputbuf_delete (struct inputbuf *ib) 75 { 76 ringbuf_delete (ib->rb); 77 free (ib); 78 } 79 80 int inputbuf_io_error(struct inputbuf * ib)81inputbuf_io_error (struct inputbuf *ib) 82 { 83 return ib->err; 84 } 85 86 int inputbuf_get(struct inputbuf * ib)87inputbuf_get (struct inputbuf *ib) 88 { 89 int c; 90 if (ib->saving) 91 { 92 c = ringbuf_reader_get (ib->reader); 93 if (c == EOF && ringbuf_space_avail (ib->rb)) 94 { 95 errno = 0; 96 c = getc (ib->file); 97 if (c == EOF) 98 ib->err = errno; 99 else 100 ringbuf_put (ib->rb, c); 101 } 102 if (c != EOF) 103 ++ib->saved_count; 104 } 105 else 106 { 107 c = ringbuf_get (ib->rb); 108 if (c == EOF) 109 { 110 errno = 0; 111 c = getc (ib->file); 112 } 113 if (c == EOF) 114 ib->err = errno; 115 else 116 ++ib->count; 117 } 118 return c; 119 } 120 121 int inputbuf_saving(struct inputbuf * ib)122inputbuf_saving (struct inputbuf *ib) 123 { 124 if (ib->saving) 125 return 1; 126 ib->saving = 1; 127 ib->saved_count = 0; 128 ringbuf_reader_reset (ib->reader); 129 return 0; 130 } 131 132 int inputbuf_rewind(struct inputbuf * ib)133inputbuf_rewind (struct inputbuf *ib) 134 { 135 ringbuf_reader_reset (ib->reader); 136 ib->saving = 0; 137 return 0; 138 } 139 140 int inputbuf_forget(struct inputbuf * ib)141inputbuf_forget (struct inputbuf *ib) 142 { 143 if (!ib->saving) 144 return 1; 145 ringbuf_reader_consume (ib->reader); 146 ib->saving = 0; 147 ib->count += ib->saved_count; 148 return 0; 149 } 150 151 size_t inputbuf_get_count(struct inputbuf * ib)152inputbuf_get_count (struct inputbuf *ib) 153 { 154 return ib->count; 155 } 156 157 void inputbuf_reset_count(struct inputbuf * ib)158inputbuf_reset_count (struct inputbuf *ib) 159 { 160 ib->count = 0; 161 ib->saved_count = 0; 162 } 163 164 int inputbuf_avail(struct inputbuf * ib)165inputbuf_avail (struct inputbuf *ib) 166 { 167 return ib->saving ? !ringbuf_reader_at_end (ib->reader) 168 : !ringbuf_is_empty (ib->rb); 169 } 170 171