2 * UCW Library -- Fast Buffered I/O on Growing Buffers
4 * (c) 2006 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 #include "lib/fastbuf.h"
19 #define FB_GBUF(f) ((struct fb_gbuf *)(f)->is_fastbuf)
22 fbgrow_refill(struct fastbuf *b)
24 if (b->bstop != FB_GBUF(b)->last_written)
26 /* There was an intervening flush */
27 b->bstop = FB_GBUF(b)->last_written;
28 b->pos = b->bstop - b->buffer;
31 /* We are at the end */
36 fbgrow_spout(struct fastbuf *b)
38 if (b->bptr >= b->bufend)
40 uns len = b->bufend - b->buffer;
41 b->buffer = xrealloc(b->buffer, 2*len);
42 b->bufend = b->buffer + 2*len;
44 b->bptr = b->buffer + len;
49 fbgrow_seek(struct fastbuf *b, sh_off_t pos, int whence)
51 ASSERT(FB_GBUF(b)->last_written); /* Seeks allowed only in read mode */
52 sh_off_t len = FB_GBUF(b)->last_written - b->buffer;
53 if (whence == SEEK_END)
55 ASSERT(pos >= 0 && pos <= len);
56 b->bptr = b->buffer + pos;
57 b->bstop = FB_GBUF(b)->last_written;
62 fbgrow_close(struct fastbuf *b)
69 fbgrow_create(unsigned basic_size)
71 struct fastbuf *b = xmalloc_zero(sizeof(struct fb_gbuf));
72 b->buffer = xmalloc(basic_size);
73 b->bufend = b->buffer + basic_size;
74 b->bptr = b->bstop = b->buffer;
76 b->refill = fbgrow_refill;
77 b->spout = fbgrow_spout;
78 b->seek = fbgrow_seek;
79 b->close = fbgrow_close;
80 b->can_overwrite_buffer = 1;
85 fbgrow_reset(struct fastbuf *b)
87 b->bptr = b->bstop = b->buffer;
89 FB_GBUF(b)->last_written = NULL;
93 fbgrow_rewind(struct fastbuf *b)
95 if (!FB_GBUF(b)->last_written)
97 /* Last operation was a write, so remember the end position */
98 FB_GBUF(b)->last_written = b->bptr;
101 b->bstop = FB_GBUF(b)->last_written;
102 b->pos = b->bstop - b->buffer;
112 f = fbgrow_create(3);
113 for (uns i=0; i<5; i++)
116 bwrite(f, "12345", 5);
117 bwrite(f, "12345", 5);
118 printf("<%d>", (int)btell(f));
120 printf("<%d>", (int)btell(f));
122 printf("<%d>", (int)btell(f));
123 while ((t = bgetc(f)) >= 0)
125 printf("<%d>", (int)btell(f));
127 bseek(f, -1, SEEK_END);
128 printf("<%d>", (int)btell(f));
129 while ((t = bgetc(f)) >= 0)
131 printf("<%d>\n", (int)btell(f));