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 *bb)
289 byte *buf = bb->ptr, *src;
290 uns len = 0, buf_len = bb->len, src_len = bdirect_read_prepare(f, &src);
293 uns cnt = MIN(src_len, buf_len);
294 for (uns i = cnt; i--;)
299 return buf - bb->ptr;
305 src_len = bdirect_read_prepare(f, &src);
310 bb_do_grow(bb, len + 1);
312 buf_len = bb->len - len;
322 bgets_mp(struct mempool *mp, struct fastbuf *f)
324 #define BLOCK_SIZE 4096
327 byte data[BLOCK_SIZE];
332 struct block *new_block = alloca(sizeof(struct block));
333 byte *b = new_block->data, *e = b + BLOCK_SIZE;
337 if (k == '\n' || k < 0)
339 uns len = b - new_block->data;
340 byte *result = mp_alloc(mp, sum + len + 1) + sum;
342 memcpy(result, new_block->data, len);
345 result -= BLOCK_SIZE;
346 memcpy(result, blocks->data, BLOCK_SIZE);
347 blocks = blocks->prev;
353 new_block->prev = blocks;
361 bgets_stk_step(struct fastbuf *f, byte *old_buf, byte *buf, uns len)
366 memcpy(buf, old_buf, len);
372 if (k == '\n' || k < 0)
380 bgets0(struct fastbuf *f, byte *b, uns l)
398 die("%s: Line too long", f->name);
402 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
407 uns favail, tavail, n;
409 favail = bdirect_read_prepare(f, &fptr);
414 die("bbcopy: source exhausted");
416 tavail = bdirect_write_prepare(t, &tptr);
419 memcpy(tptr, fptr, n);
420 bdirect_read_commit(f, fptr + n);
421 bdirect_write_commit(t, tptr + n);
428 bconfig(struct fastbuf *f, uns item, int value)
430 return f->config ? f->config(f, item, value) : -1;
434 brewind(struct fastbuf *f)
441 bskip_slow(struct fastbuf *f, uns len)
446 uns l = bdirect_read_prepare(f, &buf);
450 bdirect_read_commit(f, buf+l);
457 bfilesize(struct fastbuf *f)
461 sh_off_t pos = btell(f);
462 bseek(f, 0, SEEK_END);
463 sh_off_t len = btell(f);