2 * UCW Library -- Fast Buffered I/O
4 * (c) 1997--2007 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 "ucw/fastbuf.h"
12 #include "ucw/respool.h"
13 #include "ucw/trans.h"
18 void bclose(struct fastbuf *f)
22 if (!(f->flags & FB_DEAD))
31 void NONRET bthrow(struct fastbuf *f, const char *id, const char *fmt, ...)
33 ASSERT(!(f->flags & FB_DEAD));
37 trans_vthrow(id, f, fmt, args);
40 int brefill(struct fastbuf *f, int allow_eof)
42 ASSERT(f->bptr >= f->bstop);
44 bthrow(f, "fb.read", "Stream not readable");
47 ASSERT(f->bptr < f->bstop);
52 if (!allow_eof && (f->flags & FB_DIE_ON_EOF))
53 bthrow(f, "fb.eof", "Unexpected EOF");
54 ASSERT(f->bptr == f->bstop);
59 void bspout(struct fastbuf *f)
61 ASSERT(f->bptr > f->bstop || f->bptr >= f->bufend);
63 bthrow(f, "fb.write", "Stream not writeable");
65 ASSERT(f->bptr < f->bufend);
68 void bflush(struct fastbuf *f)
70 if (f->bptr > f->bstop)
72 else if (f->bstop > f->buffer)
73 f->bptr = f->bstop = f->buffer;
76 inline void bsetpos(struct fastbuf *f, ucw_off_t pos)
78 /* We can optimize seeks only when reading */
79 if (pos >= f->pos - (f->bstop - f->buffer) && pos <= f->pos)
80 f->bptr = f->bstop + (pos - f->pos);
84 if (!f->seek || !f->seek(f, pos, SEEK_SET))
85 bthrow(f, "fb.seek", "Stream not seekable");
89 void bseek(struct fastbuf *f, ucw_off_t pos, int whence)
94 return bsetpos(f, pos);
96 return bsetpos(f, btell(f) + pos);
99 if (!f->seek || !f->seek(f, pos, SEEK_END))
100 bthrow(f, "fb.seek", "Stream not seekable");
103 die("bseek: invalid whence=%d", whence);
107 int bgetc_slow(struct fastbuf *f)
109 if (f->bptr < f->bstop)
116 int bpeekc_slow(struct fastbuf *f)
118 if (f->bptr < f->bstop)
125 int beof_slow(struct fastbuf *f)
127 return f->bptr >= f->bstop && !brefill(f, 1);
130 void bputc_slow(struct fastbuf *f, uns c)
132 if (f->bptr >= f->bufend)
137 uns bread_slow(struct fastbuf *f, void *b, uns l, uns check)
142 uns k = f->bstop - f->bptr;
147 k = f->bstop - f->bptr;
153 memcpy(b, f->bptr, k);
159 if (check && total && l)
160 bthrow(f, "fb.read", "breadb: short read");
164 void bwrite_slow(struct fastbuf *f, const void *b, uns l)
168 uns k = f->bufend - f->bptr;
173 k = f->bufend - f->bptr;
177 memcpy(f->bptr, b, k);
185 bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l)
190 uns favail, tavail, n;
192 favail = bdirect_read_prepare(f, &fptr);
197 die("bbcopy: source exhausted");
199 tavail = bdirect_write_prepare(t, &tptr);
202 memcpy(tptr, fptr, n);
203 bdirect_read_commit(f, fptr + n);
204 bdirect_write_commit(t, tptr + n);
211 bconfig(struct fastbuf *f, uns item, int value)
213 return f->config ? f->config(f, item, value) : -1;
217 brewind(struct fastbuf *f)
224 bskip_slow(struct fastbuf *f, uns len)
229 uns l = bdirect_read_prepare(f, &buf);
233 bdirect_read_commit(f, buf+l);
240 bfilesize(struct fastbuf *f)
244 ucw_off_t pos = btell(f);
246 if (!f->seek(f, 0, SEEK_END))
248 ucw_off_t len = btell(f);
256 fb_res_detach(struct resource *r)
258 struct fastbuf *f = r->priv;
263 fb_res_free(struct resource *r)
265 struct fastbuf *f = r->priv;
271 fb_res_dump(struct resource *r)
273 struct fastbuf *f = r->priv;
274 printf(" name=%s", f->name);
277 static const struct res_class fb_res_class = {
279 .detach = fb_res_detach,
285 fb_tie(struct fastbuf *f)
287 f->res = res_new(&fb_res_class, f);