X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Ffastbuf.c;h=b7be624b5645d5ac34e1e52ca83b1ce2a951be62;hb=cd5b7ea487ab7692635ba7eca98fcb55f6d996a7;hp=1895e9bd5d892893135f348dd1312a8ca377279c;hpb=753302b5281e6ed889cfd1ed755a7104cc421802;p=libucw.git diff --git a/lib/fastbuf.c b/lib/fastbuf.c index 1895e9bd..b7be624b 100644 --- a/lib/fastbuf.c +++ b/lib/fastbuf.c @@ -2,12 +2,14 @@ * Sherlock Library -- Fast Buffered I/O * * (c) 1997--2000 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. */ #include "lib/lib.h" #include "lib/fastbuf.h" -#include #include void bclose(struct fastbuf *f) @@ -15,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); @@ -80,20 +77,26 @@ int bpeekc_slow(struct fastbuf *f) return *f->bptr; } -void bputc_slow(struct fastbuf *f, byte c) +void bputc_slow(struct fastbuf *f, uns c) { if (f->bptr >= f->bufend) f->spout(f); *f->bptr++ = c; } -word bgetw_slow(struct fastbuf *f) +int bgetw_slow(struct fastbuf *f) { - word w = bgetc_slow(f); + int w1, w2; + w1 = bgetc_slow(f); + if (w1 < 0) + return w1; + w2 = bgetc_slow(f); + if (w2 < 0) + return w2; #ifdef CPU_BIG_ENDIAN - return (w << 8) | bgetc_slow(f); + return (w1 << 8) | w2; #else - return w | (bgetc_slow(f) << 8); + return w1 | (w2 << 8); #endif } @@ -137,7 +140,7 @@ u64 bget5_slow(struct fastbuf *f) return ((u64) h << 32) | l; } -void bputw_slow(struct fastbuf *f, word w) +void bputw_slow(struct fastbuf *f, uns w) { #ifdef CPU_BIG_ENDIAN bputc_slow(f, w >> 8); @@ -187,7 +190,7 @@ void bput5_slow(struct fastbuf *f, u64 o) #endif } -uns bread_slow(struct fastbuf *f, void *b, uns l) +uns bread_slow(struct fastbuf *f, void *b, uns l, uns check) { uns total = 0; while (l) @@ -209,6 +212,8 @@ uns bread_slow(struct fastbuf *f, void *b, uns l) l -= k; total += k; } + if (check && total && l) + die("breadb: short read"); return total; } @@ -253,3 +258,52 @@ bgets(struct fastbuf *f, byte *b, uns l) } die("%s: Line too long", f->name); } + +byte * +bgets0(struct fastbuf *f, byte *b, uns l) +{ + byte *e = b + l - 1; + int k; + + k = bgetc(f); + if (k == EOF) + return NULL; + while (b < e) + { + if (!k || k == EOF) + { + *b = 0; + return b; + } + *b++ = k; + k = bgetc(f); + } + die("%s: Line too long", f->name); +} + +void +bbcopy_slow(struct fastbuf *f, struct fastbuf *t, uns l) +{ + while (l) + { + byte *fptr, *tptr; + uns favail, tavail, n; + + favail = bdirect_read_prepare(f, &fptr); + if (!favail) + 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); + l -= n; + } +} + +int +bconfig(struct fastbuf *f, uns item, int value) +{ + return f->config ? f->config(f, item, value) : -1; +}