2 * UCW Library -- Fast Buffered I/O
4 * (c) 1997--2005 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 #include "lib/fastbuf.h"
12 #include "lib/mempool.h"
16 void bclose(struct fastbuf *f)
26 void bflush(struct fastbuf *f)
28 if (f->bptr > f->bstop)
30 else if (f->bstop > f->buffer)
31 f->bptr = f->bstop = f->buffer;
34 inline void bsetpos(struct fastbuf *f, sh_off_t pos)
36 /* We can optimize seeks only when reading */
37 if (pos >= f->pos - (f->bstop - f->buffer) && pos <= f->pos)
38 f->bptr = f->bstop + (pos - f->pos);
42 f->seek(f, pos, SEEK_SET);
46 void bseek(struct fastbuf *f, sh_off_t pos, int whence)
51 return bsetpos(f, pos);
53 return bsetpos(f, btell(f) + pos);
56 f->seek(f, pos, SEEK_END);
59 die("bseek: invalid whence=%d", whence);
63 int bgetc_slow(struct fastbuf *f)
65 if (f->bptr < f->bstop)
72 int bpeekc_slow(struct fastbuf *f)
74 if (f->bptr < f->bstop)
81 void bputc_slow(struct fastbuf *f, uns c)
83 if (f->bptr >= f->bufend)
88 int bgetw_slow(struct fastbuf *f)
98 return (w1 << 8) | w2;
100 return w1 | (w2 << 8);
104 u32 bgetl_slow(struct fastbuf *f)
106 u32 l = bgetc_slow(f);
107 #ifdef CPU_BIG_ENDIAN
108 l = (l << 8) | bgetc_slow(f);
109 l = (l << 8) | bgetc_slow(f);
110 return (l << 8) | bgetc_slow(f);
112 l = (bgetc_slow(f) << 8) | l;
113 l = (bgetc_slow(f) << 16) | l;
114 return (bgetc_slow(f) << 24) | l;
118 u64 bgetq_slow(struct fastbuf *f)
121 #ifdef CPU_BIG_ENDIAN
128 return ((u64) h << 32) | l;
131 u64 bget5_slow(struct fastbuf *f)
134 #ifdef CPU_BIG_ENDIAN
141 return ((u64) h << 32) | l;
144 void bputw_slow(struct fastbuf *f, uns w)
146 #ifdef CPU_BIG_ENDIAN
147 bputc_slow(f, w >> 8);
151 bputc_slow(f, w >> 8);
155 void bputl_slow(struct fastbuf *f, u32 l)
157 #ifdef CPU_BIG_ENDIAN
158 bputc_slow(f, l >> 24);
159 bputc_slow(f, l >> 16);
160 bputc_slow(f, l >> 8);
164 bputc_slow(f, l >> 8);
165 bputc_slow(f, l >> 16);
166 bputc_slow(f, l >> 24);
170 void bputq_slow(struct fastbuf *f, u64 q)
172 #ifdef CPU_BIG_ENDIAN
173 bputl_slow(f, q >> 32);
177 bputl_slow(f, q >> 32);
181 void bput5_slow(struct fastbuf *f, u64 o)
185 #ifdef CPU_BIG_ENDIAN
194 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
199 uns k = f->bstop - f->bptr;
204 k = f->bstop - f->bptr;
210 memcpy(b, f->bptr, k);
216 if (check && total && l)
217 die("breadb: short read");
221 void bwrite_slow(struct fastbuf *f, void *b, uns l)
225 uns k = f->bufend - f->bptr;
230 k = f->bufend - f->bptr;
234 memcpy(f->bptr, b, k);
241 byte * /* Non-standard */
242 bgets(struct fastbuf *f, byte *b, uns l)
252 if (k == '\n' || k < 0)
260 die("%s: Line too long", f->name);
264 bgets_nodie(struct fastbuf *f, byte *b, uns l)
275 if (k == '\n' || k < 0)
287 bgets_bb(struct fastbuf *f, bb_t *b)
289 for (uns l = 0;; l++)
292 byte *p = bb_grow(b, l + 1) + l;
293 if (k == '\n' || k < 0)
303 bgets_mp(struct mempool *mp, struct fastbuf *f)
305 uns len = 256, l = 0;
306 byte *buf = alloca(len);
312 if (k == '\n' || k < 0)
314 byte *result = mp_alloc(mp, l + 1);
315 memcpy(result, buf, l);
325 memcpy(buf, old_buf, old_len);
330 bgets_stk_step(struct fastbuf *f, byte *old_buf, byte *buf, uns len)
335 memcpy(buf, old_buf, len);
341 if (k == '\n' || k < 0)
349 bgets0(struct fastbuf *f, byte *b, uns l)
367 die("%s: Line too long", f->name);
371 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
376 uns favail, tavail, n;
378 favail = bdirect_read_prepare(f, &fptr);
383 die("bbcopy: source exhausted");
385 tavail = bdirect_write_prepare(t, &tptr);
388 memcpy(tptr, fptr, n);
389 bdirect_read_commit(f, fptr + n);
390 bdirect_write_commit(t, tptr + n);
397 bconfig(struct fastbuf *f, uns item, int value)
399 return f->config ? f->config(f, item, value) : -1;
403 brewind(struct fastbuf *f)
410 bskip_slow(struct fastbuf *f, uns len)
415 uns l = bdirect_read_prepare(f, &buf);
419 bdirect_read_commit(f, buf+l);
426 bfilesize(struct fastbuf *f)
430 sh_off_t pos = btell(f);
431 bseek(f, 0, SEEK_END);
432 sh_off_t len = btell(f);