From 2cbbf299beda4d0f108e753d46341d89184dfd46 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Fri, 17 Mar 2006 22:02:05 +0100 Subject: [PATCH] Added a recyclable fastbuf over a growing buffer. (Ideal for use in the indexer.) --- lib/Makefile | 2 +- lib/fastbuf.h | 6 +++ lib/fb-gbuf.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 lib/fb-gbuf.c diff --git a/lib/Makefile b/lib/Makefile index bf3ede45..451a11d8 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -14,7 +14,7 @@ LIBUCW_MODS= \ conf ipaccess \ profile \ fastbuf ff-printf ff-utf8 \ - fb-file carefulio fb-mem fb-temp fb-mmap fb-limfd fb-buffer \ + fb-file carefulio fb-mem fb-temp fb-mmap fb-limfd fb-buffer fb-gbuf \ str_ctype str_upper str_lower unicode-utf8 stkstring \ wildmatch wordsplit ctmatch patimatch patmatch regex \ prime primetable random timer randomkey \ diff --git a/lib/fastbuf.h b/lib/fastbuf.h index 905d046d..c2e12419 100644 --- a/lib/fastbuf.h +++ b/lib/fastbuf.h @@ -109,6 +109,12 @@ fbbuf_count_written(struct fastbuf *f) return f->bptr - f->bstop; } +/* FastIO on recyclable growing buffers */ + +struct fastbuf *fbgbuf_create(unsigned basic_size); +void fbgbuf_write(struct fastbuf *b); /* Reset stream and prepare for writing */ +void fbgbuf_rewind(struct fastbuf *b); /* Close reading if needed and prepare for reading */ + /* Configuring stream parameters */ int bconfig(struct fastbuf *f, uns type, int data); diff --git a/lib/fb-gbuf.c b/lib/fb-gbuf.c new file mode 100644 index 00000000..23059a54 --- /dev/null +++ b/lib/fb-gbuf.c @@ -0,0 +1,137 @@ +/* + * UCW Library -- Fast Buffered I/O on Growing Buffers + * + * (c) 2006 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 + +struct fb_gbuf { + struct fastbuf fb; + byte *last_written; +}; +#define FB_GBUF(f) ((struct fb_gbuf *)(f)->is_fastbuf) + +static int +fbgbuf_refill(struct fastbuf *b) +{ + if (b->bstop != FB_GBUF(b)->last_written) + { + /* There was an intervening flush */ + b->bstop = FB_GBUF(b)->last_written; + b->pos = b->bstop - b->buffer; + return 1; + } + /* We are at the end */ + return 0; +} + +static void +fbgbuf_spout(struct fastbuf *b) +{ + if (b->bptr >= b->bufend) + { + uns len = b->bufend - b->buffer; + b->buffer = xrealloc(b->buffer, 2*len); + b->bufend = b->buffer + 2*len; + b->bstop = b->buffer; + b->bptr = b->buffer + len; + } +} + +static void +fbgbuf_seek(struct fastbuf *b, sh_off_t pos, int whence) +{ + ASSERT(FB_GBUF(b)->last_written); /* Seeks allowed only in read mode */ + sh_off_t len = FB_GBUF(b)->last_written - b->buffer; + if (whence == SEEK_END) + pos += len; + ASSERT(pos >= 0 && pos <= len); + b->bptr = b->buffer + pos; + b->bstop = FB_GBUF(b)->last_written; + b->pos = len; +} + +static void +fbgbuf_close(struct fastbuf *b) +{ + xfree(b->buffer); + xfree(b); +} + +struct fastbuf * +fbgbuf_create(unsigned basic_size) +{ + struct fastbuf *b = xmalloc_zero(sizeof(struct fb_gbuf)); + b->buffer = xmalloc(basic_size); + b->bufend = b->buffer + basic_size; + b->bptr = b->bstop = b->buffer; + b->name = ""; + b->refill = fbgbuf_refill; + b->spout = fbgbuf_spout; + b->seek = fbgbuf_seek; + b->close = fbgbuf_close; + b->can_overwrite_buffer = 1; + return b; +} + +void +fbgbuf_write(struct fastbuf *b) +{ + b->bptr = b->bstop = b->buffer; + b->pos = 0; + FB_GBUF(b)->last_written = NULL; +} + +void +fbgbuf_rewind(struct fastbuf *b) +{ + if (!FB_GBUF(b)->last_written) + { + /* Last operation was a write, so remember the end position */ + FB_GBUF(b)->last_written = b->bptr; + } + b->bptr = b->buffer; + b->bstop = FB_GBUF(b)->last_written; + b->pos = b->bstop - b->buffer; +} + +#ifdef TEST + +int main(void) +{ + struct fastbuf *f; + int t; + + f = fbgbuf_create(3); + for (uns i=0; i<5; i++) + { + fbgbuf_write(f); + bwrite(f, "12345", 5); + bwrite(f, "12345", 5); + printf("<%d>", (int)btell(f)); + bflush(f); + printf("<%d>", (int)btell(f)); + fbgbuf_rewind(f); + printf("<%d>", (int)btell(f)); + while ((t = bgetc(f)) >= 0) + putchar(t); + printf("<%d>", (int)btell(f)); + fbgbuf_rewind(f); + bseek(f, -1, SEEK_END); + printf("<%d>", (int)btell(f)); + while ((t = bgetc(f)) >= 0) + putchar(t); + printf("<%d>\n", (int)btell(f)); + } + bclose(f); + return 0; +} + +#endif -- 2.39.2