X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Ffastbuf.c;h=85df8250370f10197234d902f4cbcc908fd73895;hb=a010e5f6e075097c0d6362d40fb49e812e99e185;hp=9f5d36924da5dbbbb88e1b76227d96c6d0bcb694;hpb=49ed04e2e93a6a5b01058638224621d5c07db01c;p=libucw.git diff --git a/lib/fastbuf.c b/lib/fastbuf.c index 9f5d3692..85df8250 100644 --- a/lib/fastbuf.c +++ b/lib/fastbuf.c @@ -1,7 +1,7 @@ /* * Sherlock Library -- Fast Buffered I/O * - * (c) 1997--2000 Martin Mares + * (c) 1997--2004 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -10,7 +10,6 @@ #include "lib/lib.h" #include "lib/fastbuf.h" -#include #include void bclose(struct fastbuf *f) @@ -18,29 +17,24 @@ void bclose(struct fastbuf *f) if (f) { bflush(f); - f->close(f); - xfree(f); + if (f->close) + f->close(f); } } void bflush(struct fastbuf *f) { - if (f->bptr != f->buffer) - { /* Have something to flush */ - if (f->bstop > f->buffer) /* Read data? */ - { - f->bptr = f->bstop = f->buffer; - f->pos = f->fdpos; - } - else /* Write data... */ - f->spout(f); - } + if (f->bptr > f->bstop) + f->spout(f); + else if (f->bstop > f->buffer) + f->bptr = f->bstop = f->buffer; } inline void bsetpos(struct fastbuf *f, sh_off_t pos) { - if (pos >= f->pos && (pos <= f->pos + (f->bptr - f->buffer) || pos <= f->pos + (f->bstop - f->buffer))) - f->bptr = f->buffer + (pos - f->pos); + /* We can optimize seeks only when reading */ + if (pos >= f->pos - (f->bstop - f->buffer) && pos <= f->pos) + f->bptr = f->bstop + (pos - f->pos); else { bflush(f); @@ -250,11 +244,11 @@ bgets(struct fastbuf *f, byte *b, uns l) int k; k = bgetc(f); - if (k == EOF) + if (k < 0) return NULL; while (b < e) { - if (k == '\n' || k == EOF) + if (k == '\n' || k < 0) { *b = 0; return b; @@ -265,6 +259,29 @@ bgets(struct fastbuf *f, byte *b, uns l) die("%s: Line too long", f->name); } +int +bgets_nodie(struct fastbuf *f, byte *b, uns l) +{ + byte *start = b; + byte *e = b + l - 1; + int k; + + k = bgetc(f); + if (k < 0) + return 0; + while (b < e) + { + if (k == '\n' || k < 0) + { + *b++ = 0; + return b - start; + } + *b++ = k; + k = bgetc(f); + } + return -1; +} + byte * bgets0(struct fastbuf *f, byte *b, uns l) { @@ -272,11 +289,11 @@ bgets0(struct fastbuf *f, byte *b, uns l) int k; k = bgetc(f); - if (k == EOF) + if (k < 0) return NULL; while (b < e) { - if (!k || k == EOF) + if (k <= 0) { *b = 0; return b; @@ -287,30 +304,66 @@ bgets0(struct fastbuf *f, byte *b, uns l) die("%s: Line too long", f->name); } -int -bdirect_read(struct fastbuf *f, byte **buf) +void +bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l) { - int len; + while (l) + { + byte *fptr, *tptr; + uns favail, tavail, n; - if (f->bptr == f->bstop && !f->refill(f)) - return EOF; - *buf = f->bptr; - len = f->bstop - f->bptr; - f->bptr += len; - return len; + favail = bdirect_read_prepare(f, &fptr); + if (!favail) + { + if (l == ~0U) + return; + die("bbcopy: source exhausted"); + } + tavail = bdirect_write_prepare(t, &tptr); + n = MIN(l, favail); + n = MIN(n, tavail); + memcpy(tptr, fptr, n); + bdirect_read_commit(f, fptr + n); + bdirect_write_commit(t, tptr + n); + if (l != ~0U) + l -= n; + } } int -bdirect_write_prepare(struct fastbuf *f, byte **buf) +bconfig(struct fastbuf *f, uns item, int value) { - if (f->bptr == f->bufend) - f->spout(f); - *buf = f->bptr; - return f->bufend - f->bptr; + return f->config ? f->config(f, item, value) : -1; } void -bdirect_write_commit(struct fastbuf *f, byte *pos) +brewind(struct fastbuf *f) { - f->bptr = pos; + bflush(f); + bsetpos(f, 0); +} + +void +bskip(struct fastbuf *f, uns len) +{ + while (len) + { + byte *buf; + uns l = bdirect_read_prepare(f, &buf); + l = MIN(l, len); + bdirect_read_commit(f, buf+l); + len -= l; + } +} + +sh_off_t +bfilesize(struct fastbuf *f) +{ + if (!f) + return 0; + sh_off_t pos = btell(f); + bseek(f, 0, SEEK_END); + sh_off_t len = btell(f); + bsetpos(f, pos); + return len; }