From 1641c17df8008adfb4720052ec01e427543cdd94 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 28 Jul 1997 15:45:47 +0000 Subject: [PATCH] x --- lib/config.h | 7 ++ lib/fastbuf.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/fastbuf.h | 213 ++++++++++++++++++++++++++++++++++ lib/url.c | 2 +- 4 files changed, 529 insertions(+), 1 deletion(-) create mode 100644 lib/fastbuf.c create mode 100644 lib/fastbuf.h diff --git a/lib/config.h b/lib/config.h index 8b09c820..bbed4d5d 100644 --- a/lib/config.h +++ b/lib/config.h @@ -18,6 +18,13 @@ typedef unsigned int ulg; /* exactly 32 bits, unsigned */ typedef int slg; /* exactly 32 bits, signed */ typedef unsigned int uns; /* at least 32 bits */ +/* CPU characteristics */ + +#define CPU_LITTLE_ENDIAN +#undef CPU_BIG_ENDIAN +#define CPU_CAN_DO_UNALIGNED_WORDS +#define CPU_CAN_DO_UNALIGNED_LONGS + /* Misc */ #ifdef __GNUC__ diff --git a/lib/fastbuf.c b/lib/fastbuf.c new file mode 100644 index 00000000..9756c978 --- /dev/null +++ b/lib/fastbuf.c @@ -0,0 +1,308 @@ +/* + * Sherlock Library -- Fast File Buffering + * + * (c) 1997 Martin Mares, + */ + +#include +#include +#include +#include +#include + +#include "lib.h" +#include "fastbuf.h" + +struct fastbuf *__bfdopen(int fd, uns buffer, byte *name) +{ + struct fastbuf *b = xmalloc(sizeof(struct fastbuf)); + + b->buflen = buffer; + b->buffer = xmalloc(buffer); + b->bptr = b->bstop = b->buffer; + b->bufend = b->buffer + buffer; + b->name = stralloc(name); + b->pos = b->fdpos = 0; + b->fd = fd; + return b; +} + +struct fastbuf * +bopen(byte *name, uns mode, uns buffer) +{ + int fd = open(name, mode, 0666); + + if (fd < 0) + die("Unable to %s file %s: %m", + (mode & O_CREAT) ? "create" : "open", name); + return __bfdopen(fd, buffer, name); +} + +struct fastbuf * +bfdopen(int fd, uns buffer) +{ + byte x[32]; + + sprintf(x, "fd%d", fd); + return __bfdopen(fd, buffer, x); +} + +void bclose(struct fastbuf *f) +{ + bflush(f); + close(f->fd); + free(f->name); + free(f->buffer); + free(f); +} + +static int +rdbuf(struct fastbuf *f) +{ + int l = read(f->fd, f->buffer, f->buflen); + + if (l < 0) + die("Error reading %s: %m", f->name); + f->bptr = f->buffer; + f->bstop = f->buffer + l; + f->pos = f->fdpos; + f->fdpos += l; + return l; +} + +static void +wrbuf(struct fastbuf *f) +{ + int l = f->bptr - f->buffer; + + if (l) + { + if (write(f->fd, f->buffer, l) != l) + die("Error writing %s: %m"); + f->bptr = f->buffer; + f->fdpos += l; + f->pos = f->fdpos; + } +} + +void bflush(struct fastbuf *f) +{ + if (f->bptr != f->buffer) + { /* Have something to flush */ + if (f->bstop > f->buffer) + { /* And it's read data */ + f->bptr = f->bstop = f->buffer; + } + else + { /* Write data */ + wrbuf(f); + } + } +} + +inline void bsetpos(struct fastbuf *f, uns 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); + } + else + { + bflush(f); + if (f->fdpos != pos && lseek(f->fd, pos, SEEK_SET) < 0) + die("lseek on %s: %m", f->name); + f->fdpos = f->pos = pos; + } +} + +void bseek(struct fastbuf *f, uns pos, int whence) +{ + int l; + + switch (whence) + { + case SEEK_SET: + return bsetpos(f, pos); + case SEEK_CUR: + return bsetpos(f, btell(f) + pos); + case SEEK_END: + bflush(f); + l = lseek(f->fd, pos, whence); + if (l < 0) + die("lseek on %s: %m", f->name); + f->fdpos = f->pos = l; + break; + default: + die("bseek: invalid whence=%d", whence); + } +} + +int bgetc_slow(struct fastbuf *f) +{ + if (f->bptr < f->bstop) + return *f->bptr++; + if (!rdbuf(f)) + return EOF; + return *f->bptr++; +} + +void bputc_slow(struct fastbuf *f, byte c) +{ + if (f->bptr >= f->bufend) + wrbuf(f); + *f->bptr++ = c; +} + +word bgetw_slow(struct fastbuf *f) +{ + word w = bgetc_slow(f); +#ifdef CPU_BIG_ENDIAN + return (w << 8) | bgetc_slow(f); +#else + return w | (bgetc_slow(f) << 8); +#endif +} + +ulg bgetl_slow(struct fastbuf *f) +{ + ulg l = bgetc_slow(f); +#ifdef CPU_BIG_ENDIAN + l = (l << 8) | bgetc_slow(f); + l = (l << 8) | bgetc_slow(f); + return (l << 8) | bgetc_slow(f); +#else + l = (bgetc_slow(f) << 8) | l; + l = (bgetc_slow(f) << 16) | l; + return (bgetc_slow(f) << 24) | l; +#endif +} + +void bputw_slow(struct fastbuf *f, word w) +{ +#ifdef CPU_BIG_ENDIAN + bputc_slow(f, w >> 8); + bputc_slow(f, w); +#else + bputc_slow(f, w); + bputc_slow(f, w >> 8); +#endif +} + +void bputl_slow(struct fastbuf *f, ulg l) +{ +#ifdef CPU_BIG_ENDIAN + bputc_slow(f, l >> 24); + bputc_slow(f, l >> 16); + bputc_slow(f, l >> 8); + bputc_slow(f, l); +#else + bputc_slow(f, l); + bputc_slow(f, l >> 8); + bputc_slow(f, l >> 16); + bputc_slow(f, l >> 24); +#endif +} + +void bread_slow(struct fastbuf *f, void *b, uns l) +{ + while (l) + { + uns k = f->bstop - f->bptr; + + if (!k) + { + rdbuf(f); + k = f->bstop - f->bptr; + if (!k) + die("bread on %s: file exhausted", f->name); + } + if (k > l) + k = l; + memcpy(b, f->bptr, k); + f->bptr += k; + b = (byte *)b + k; + l -= k; + } +} + +void bwrite_slow(struct fastbuf *f, void *b, uns l) +{ + while (l) + { + uns k = f->bufend - f->bptr; + + if (!k) + { + wrbuf(f); + k = f->bufend - f->bptr; + } + if (k > l) + k = l; + memcpy(f->bptr, b, k); + f->bptr += k; + b = (byte *)b + k; + l -= k; + } +} + +void bbcopy(struct fastbuf *f, struct fastbuf *t, uns l) +{ + uns rf = f->bstop - f->bptr; + uns rt = t->bufend - t->bptr; + + if (!l) + return; + if (rf && rt) + { + uns k = l; + if (k > rf) + k = rf; + if (k > rt) + k = rt; + memcpy(t->bptr, f->bptr, k); + t->bptr += k; + f->bptr += k; + l -= k; + } + while (l >= t->buflen) + { + wrbuf(t); + if (read(f->fd, t->buffer, t->buflen) != t->buflen) + die("bbcopy: %s exhausted", f->name); + f->fdpos += t->buflen; + t->bptr = t->bufend; + l -= t->buflen; + } + while (l) + { + uns k = t->bufend - t->bptr; + + if (!k) + { + wrbuf(t); + k = t->bufend - t->bptr; + } + if (k > l) + k = l; + bread(f, t->bptr, k); + t->bptr += k; + l -= k; + } +} + +#ifdef TEST + +int main(int argc, char **argv) +{ + struct fastbuf *f, *t; + int c; + + f = bopen("/etc/profile", O_RDONLY, 16); + t = bfdopen(1, 13); + bbcopy(f, t, 100); + bclose(f); + bclose(t); +} + +#endif diff --git a/lib/fastbuf.h b/lib/fastbuf.h new file mode 100644 index 00000000..8195250e --- /dev/null +++ b/lib/fastbuf.h @@ -0,0 +1,213 @@ +/* + * Sherlock Library -- Fast File Buffering + * + * (c) 1997 Martin Mares, + */ + +#ifndef EOF +#include +#endif + +struct fastbuf { + byte *bptr, *bstop; /* Access pointers */ + byte *buffer, *bufend; /* Start and end of the buffer */ + byte *name; /* File name for error messages */ + uns buflen; /* Size of standard portion of the buffer */ + uns pos; /* Position of bptr in the file */ + uns fdpos; /* Current position in the file */ + int fd; /* File descriptor */ +}; + +struct fastbuf *bopen(byte *name, uns mode, uns buffer); +struct fastbuf *bfdopen(int fd, uns buffer); +void bclose(struct fastbuf *f); +void bflush(struct fastbuf *f); + +void bseek(struct fastbuf *f, uns pos, int whence); +void bsetpos(struct fastbuf *f, uns pos); + +extern inline uns btell(struct fastbuf *f) +{ + return f->pos + (f->bptr - f->buffer); +} + +int bgetc_slow(struct fastbuf *f); +extern inline int bgetc(struct fastbuf *f) +{ + return (f->bptr < f->bstop) ? (int) *f->bptr++ : bgetc_slow(f); +} + +extern inline void bungetc(struct fastbuf *f, byte c) +{ + *--f->bptr = c; +} + +void bputc_slow(struct fastbuf *f, byte c); +extern inline void bputc(struct fastbuf *f, byte c) +{ + if (f->bptr < f->bufend) + *f->bptr++ = c; + else + bputc_slow(f, c); +} + +word bgetw_slow(struct fastbuf *f); +extern inline word bgetw(struct fastbuf *f) +{ +#ifdef CPU_CAN_DO_UNALIGNED_WORDS + word w; + if (f->bptr + 2 <= f->bstop) + { + w = * ((word *) f->bptr); + f->bptr += 2; + return w; + } + else + return bgetw_slow(f); +#else + word w = bgetc(f); +#ifdef CPU_BIG_ENDIAN + return (w << 8) | bgetc(f); +#else + return w | (bgetc(f) << 8); +#endif +#endif +} + +ulg bgetl_slow(struct fastbuf *f); +extern inline ulg bgetl(struct fastbuf *f) +{ +#ifdef CPU_CAN_DO_UNALIGNED_LONGS + ulg l; + if (f->bptr + 4 <= f->bstop) + { + l = * ((ulg *) f->bptr); + f->bptr += 4; + return l; + } + else + return bgetl_slow(f); +#else + ulg l = bgetc(f); +#ifdef CPU_BIG_ENDIAN + l = (l << 8) | bgetc(f); + l = (l << 8) | bgetc(f); + return (l << 8) | bgetc(f); +#else + l = (bgetc(f) << 8) | l; + l = (bgetc(f) << 16) | l; + return (bgetc(f) << 24) | l; +#endif +#endif +} + +void bputw_slow(struct fastbuf *f, word w); +extern inline void bputw(struct fastbuf *f, word w) +{ +#ifdef CPU_CAN_DO_UNALIGNED_WORDS + if (f->bptr + 2 <= f->bufend) + { + * ((word *) f->bptr) = w; + f->bptr += 2; + } + else + bputw_slow(f, w); +#else +#ifdef CPU_BIG_ENDIAN + bputc(f, w >> 8); + bputc(f, w); +#else + bputc(f, w); + bputc(f, w >> 8); +#endif +#endif +} + +void bputl_slow(struct fastbuf *f, ulg l); +extern inline void bputl(struct fastbuf *f, ulg l) +{ +#ifdef CPU_CAN_DO_UNALIGNED_LONGS + if (f->bptr + 4 <= f->bufend) + { + * ((ulg *) f->bptr) = l; + f->bptr += 4; + } + else + bputl_slow(f, l); +#else +#ifdef CPU_BIG_ENDIAN + bputc(f, l >> 24); + bputc(f, l >> 16); + bputc(f, l >> 8); + bputc(f, l); +#else + bputc(f, l); + bputc(f, l >> 8); + bputc(f, l >> 16); + bputc(f, l >> 24); +#endif +#endif +} + +void bread_slow(struct fastbuf *f, void *b, uns l); +extern inline void bread(struct fastbuf *f, void *b, uns l) +{ + if (f->bptr + l <= f->bstop) + { + memcpy(b, f->bptr, l); + f->bptr += l; + } + else + bread_slow(f, b, l); +} + +void bwrite_slow(struct fastbuf *f, void *b, uns l); +extern inline void bwrite(struct fastbuf *f, void *b, uns l) +{ + if (f->bptr + l <= f->bufend) + { + memcpy(f->bptr, b, l); + f->bptr += l; + } + else + bwrite_slow(f, b, l); +} + +void bbcopy(struct fastbuf *f, struct fastbuf *t, uns l); + +extern inline byte * /* Non-standard */ +bgets(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 == '\n' || k == EOF) + { + *b = 0; + return b; + } + *b++ = k; + k = bgetc(f); + } + die("%s: Line too long", f->name); +} + +extern inline void +bputs(struct fastbuf *f, byte *b) +{ + while (*b) + bputc(f, *b++); +} + +extern inline void +bputsn(struct fastbuf *f, byte *b) +{ + bputs(f, b); + bputc(f, '\n'); +} + diff --git a/lib/url.c b/lib/url.c index 7ecd066d..bf08e62b 100644 --- a/lib/url.c +++ b/lib/url.c @@ -77,7 +77,7 @@ url_enescape(byte *s, byte *d) if ( *s >= 'A' && *s <= 'Z' || *s >= 'a' && *s <= 'z' || *s >= '0' && *s <= '9' - || *s == '$' || *s == '-' || *s == '.' || *s == '+' + || *s == '$' || *s == '-' || *s == '.' || *s == '!' || *s == '*' || *s == '\'' || *s == '(' || *s == ')' || *s == '_' || *s == ';' || *s == '/' || *s == '?' || *s == ':' || *s == '@' || *s == '=' -- 2.39.2