]> mj.ucw.cz Git - libucw.git/commitdiff
Added a recyclable fastbuf over a growing buffer.
authorMartin Mares <mj@ucw.cz>
Fri, 17 Mar 2006 21:02:05 +0000 (22:02 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 17 Mar 2006 21:02:05 +0000 (22:02 +0100)
(Ideal for use in the indexer.)

lib/Makefile
lib/fastbuf.h
lib/fb-gbuf.c [new file with mode: 0644]

index bf3ede457b21cbdc7dc6a65c4e4f469b2c45adde..451a11d8089e2b191c214171bfce9ca2de44e442 100644 (file)
@@ -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 \
index 905d046d134689c2a86a2a795dd7d46a56280abc..c2e12419009b7cb07e8ac5e657ad84673b48170e 100644 (file)
@@ -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 (file)
index 0000000..23059a5
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *     UCW Library -- Fast Buffered I/O on Growing Buffers
+ *
+ *     (c) 2006 Martin Mares <mj@ucw.cz>
+ *
+ *     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 <stdlib.h>
+
+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 = "<fbgbuf>";
+  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