X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Ffastbuf.c;h=013c1b0848d3453672c38828c24bc91a4a8d09c4;hb=3f29125f27f7ee82281e49fef16ad32811cc3dcc;hp=1be1b576b1f3696baf729bb92817d802f294d66f;hpb=1571781022499a9d0c32d249f89945d034d1cbff;p=libucw.git diff --git a/lib/fastbuf.c b/lib/fastbuf.c index 1be1b576..013c1b08 100644 --- a/lib/fastbuf.c +++ b/lib/fastbuf.c @@ -2,6 +2,9 @@ * 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" @@ -12,9 +15,12 @@ void bclose(struct fastbuf *f) { - bflush(f); - f->close(f); - free(f); + if (f) + { + bflush(f); + f->close(f); + xfree(f); + } } void bflush(struct fastbuf *f) @@ -77,20 +83,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 } @@ -134,7 +146,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); @@ -184,8 +196,9 @@ void bput5_slow(struct fastbuf *f, u64 o) #endif } -void 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) { uns k = f->bstop - f->bptr; @@ -195,7 +208,7 @@ void bread_slow(struct fastbuf *f, void *b, uns l) f->refill(f); k = f->bstop - f->bptr; if (!k) - die("bread on %s: file exhausted", f->name); + break; } if (k > l) k = l; @@ -203,7 +216,11 @@ void bread_slow(struct fastbuf *f, void *b, uns l) f->bptr += k; b = (byte *)b + k; l -= k; + total += k; } + if (check && total && l) + die("breadb: short read"); + return total; } void bwrite_slow(struct fastbuf *f, void *b, uns l) @@ -247,3 +264,58 @@ 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); +} + +int +bdirect_read_prepare(struct fastbuf *f, byte **buf) +{ + int len; + + if (f->bptr == f->bstop && !f->refill(f)) + return EOF; + *buf = f->bptr; + len = f->bstop - f->bptr; + return len; +} + +void +bdirect_read_commit(struct fastbuf *f, byte *pos) +{ + f->bptr = pos; +} + +int +bdirect_write_prepare(struct fastbuf *f, byte **buf) +{ + if (f->bptr == f->bufend) + f->spout(f); + *buf = f->bptr; + return f->bufend - f->bptr; +} + +void +bdirect_write_commit(struct fastbuf *f, byte *pos) +{ + f->bptr = pos; +}