]> mj.ucw.cz Git - libucw.git/blob - lib/fastbuf.c
1b89a813998d7db2aea31dd0789a09a138d17a75
[libucw.git] / lib / fastbuf.c
1 /*
2  *      Sherlock Library -- Fast Buffered I/O
3  *
4  *      (c) 1997--2000 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/fastbuf.h"
12
13 #include <stdlib.h>
14
15 void bclose(struct fastbuf *f)
16 {
17   if (f)
18     {
19       bflush(f);
20       if (f->close)
21         f->close(f);
22     }
23 }
24
25 void bflush(struct fastbuf *f)
26 {
27   if (f->bptr != f->buffer)
28     {                                   /* Have something to flush */
29       if (f->bstop > f->buffer)         /* Read data? */
30         f->bptr = f->bstop = f->buffer;
31       else                              /* Write data... */
32         f->spout(f);
33     }
34 }
35
36 inline void bsetpos(struct fastbuf *f, sh_off_t pos)
37 {
38   /* We can optimize seeks only when reading */
39   if (pos >= f->pos - (f->bstop - f->buffer) && pos <= f->pos)
40     f->bptr = f->bstop + (pos - f->pos);
41   else
42     {
43       bflush(f);
44       f->seek(f, pos, SEEK_SET);
45     }
46 }
47
48 void bseek(struct fastbuf *f, sh_off_t pos, int whence)
49 {
50   switch (whence)
51     {
52     case SEEK_SET:
53       return bsetpos(f, pos);
54     case SEEK_CUR:
55       return bsetpos(f, btell(f) + pos);
56     case SEEK_END:
57       bflush(f);
58       f->seek(f, pos, SEEK_END);
59       break;
60     default:
61       die("bseek: invalid whence=%d", whence);
62     }
63 }
64
65 int bgetc_slow(struct fastbuf *f)
66 {
67   if (f->bptr < f->bstop)
68     return *f->bptr++;
69   if (!f->refill(f))
70     return EOF;
71   return *f->bptr++;
72 }
73
74 int bpeekc_slow(struct fastbuf *f)
75 {
76   if (f->bptr < f->bstop)
77     return *f->bptr;
78   if (!f->refill(f))
79     return EOF;
80   return *f->bptr;
81 }
82
83 void bputc_slow(struct fastbuf *f, uns c)
84 {
85   if (f->bptr >= f->bufend)
86     f->spout(f);
87   *f->bptr++ = c;
88 }
89
90 int bgetw_slow(struct fastbuf *f)
91 {
92   int w1, w2;
93   w1 = bgetc_slow(f);
94   if (w1 < 0)
95     return w1;
96   w2 = bgetc_slow(f);
97   if (w2 < 0)
98     return w2;
99 #ifdef CPU_BIG_ENDIAN
100   return (w1 << 8) | w2;
101 #else
102   return w1 | (w2 << 8);
103 #endif
104 }
105
106 u32 bgetl_slow(struct fastbuf *f)
107 {
108   u32 l = bgetc_slow(f);
109 #ifdef CPU_BIG_ENDIAN
110   l = (l << 8) | bgetc_slow(f);
111   l = (l << 8) | bgetc_slow(f);
112   return (l << 8) | bgetc_slow(f);
113 #else
114   l = (bgetc_slow(f) << 8) | l;
115   l = (bgetc_slow(f) << 16) | l;
116   return (bgetc_slow(f) << 24) | l;
117 #endif
118 }
119
120 u64 bgetq_slow(struct fastbuf *f)
121 {
122   u32 l, h;
123 #ifdef CPU_BIG_ENDIAN
124   h = bgetl_slow(f);
125   l = bgetl_slow(f);
126 #else
127   l = bgetl_slow(f);
128   h = bgetl_slow(f);
129 #endif
130   return ((u64) h << 32) | l;
131 }
132
133 u64 bget5_slow(struct fastbuf *f)
134 {
135   u32 l, h;
136 #ifdef CPU_BIG_ENDIAN
137   h = bgetc_slow(f);
138   l = bgetl_slow(f);
139 #else
140   l = bgetl_slow(f);
141   h = bgetc_slow(f);
142 #endif
143   return ((u64) h << 32) | l;
144 }
145
146 void bputw_slow(struct fastbuf *f, uns w)
147 {
148 #ifdef CPU_BIG_ENDIAN
149   bputc_slow(f, w >> 8);
150   bputc_slow(f, w);
151 #else
152   bputc_slow(f, w);
153   bputc_slow(f, w >> 8);
154 #endif
155 }
156
157 void bputl_slow(struct fastbuf *f, u32 l)
158 {
159 #ifdef CPU_BIG_ENDIAN
160   bputc_slow(f, l >> 24);
161   bputc_slow(f, l >> 16);
162   bputc_slow(f, l >> 8);
163   bputc_slow(f, l);
164 #else
165   bputc_slow(f, l);
166   bputc_slow(f, l >> 8);
167   bputc_slow(f, l >> 16);
168   bputc_slow(f, l >> 24);
169 #endif
170 }
171
172 void bputq_slow(struct fastbuf *f, u64 q)
173 {
174 #ifdef CPU_BIG_ENDIAN
175   bputl_slow(f, q >> 32);
176   bputl_slow(f, q);
177 #else
178   bputl_slow(f, q);
179   bputl_slow(f, q >> 32);
180 #endif
181 }
182
183 void bput5_slow(struct fastbuf *f, u64 o)
184 {
185   u32 hi = o >> 32;
186   u32 low = o;
187 #ifdef CPU_BIG_ENDIAN
188   bputc_slow(f, hi);
189   bputl_slow(f, low);
190 #else
191   bputl_slow(f, low);
192   bputc_slow(f, hi);
193 #endif
194 }
195
196 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
197 {
198   uns total = 0;
199   while (l)
200     {
201       uns k = f->bstop - f->bptr;
202
203       if (!k)
204         {
205           f->refill(f);
206           k = f->bstop - f->bptr;
207           if (!k)
208             break;
209         }
210       if (k > l)
211         k = l;
212       memcpy(b, f->bptr, k);
213       f->bptr += k;
214       b = (byte *)b + k;
215       l -= k;
216       total += k;
217     }
218   if (check && total && l)
219     die("breadb: short read");
220   return total;
221 }
222
223 void bwrite_slow(struct fastbuf *f, void *b, uns l)
224 {
225   while (l)
226     {
227       uns k = f->bufend - f->bptr;
228
229       if (!k)
230         {
231           f->spout(f);
232           k = f->bufend - f->bptr;
233         }
234       if (k > l)
235         k = l;
236       memcpy(f->bptr, b, k);
237       f->bptr += k;
238       b = (byte *)b + k;
239       l -= k;
240     }
241 }
242
243 byte *                                  /* Non-standard */
244 bgets(struct fastbuf *f, byte *b, uns l)
245 {
246   byte *e = b + l - 1;
247   int k;
248
249   k = bgetc(f);
250   if (k == EOF)
251     return NULL;
252   while (b < e)
253     {
254       if (k == '\n' || k == EOF)
255         {
256           *b = 0;
257           return b;
258         }
259       *b++ = k;
260       k = bgetc(f);
261     }
262   die("%s: Line too long", f->name);
263 }
264
265 byte *
266 bgets0(struct fastbuf *f, byte *b, uns l)
267 {
268   byte *e = b + l - 1;
269   int k;
270
271   k = bgetc(f);
272   if (k == EOF)
273     return NULL;
274   while (b < e)
275     {
276       if (!k || k == EOF)
277         {
278           *b = 0;
279           return b;
280         }
281       *b++ = k;
282       k = bgetc(f);
283     }
284   die("%s: Line too long", f->name);
285 }
286
287 int
288 bdirect_read_prepare(struct fastbuf *f, byte **buf)
289 {
290   if (f->bptr == f->bstop && !f->refill(f))
291     return EOF;
292   *buf = f->bptr;
293   return f->bstop - f->bptr;
294 }
295
296 void
297 bdirect_read_commit(struct fastbuf *f, byte *pos)
298 {
299   f->bptr = pos;
300 }
301
302 int
303 bdirect_write_prepare(struct fastbuf *f, byte **buf)
304 {
305   if (f->bptr == f->bufend)
306     f->spout(f);
307   *buf = f->bptr;
308   return f->bufend - f->bptr;
309 }
310
311 void
312 bdirect_write_commit(struct fastbuf *f, byte *pos)
313 {
314   f->bptr = pos;
315 }