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;
63 fbgrow_close(struct fastbuf *b)
70 fbgrow_create(unsigned basic_size)
72 struct fastbuf *b = xmalloc_zero(sizeof(struct fb_gbuf));
73 b->buffer = xmalloc(basic_size);
74 b->bufend = b->buffer + basic_size;
75 b->bptr = b->bstop = b->buffer;
77 b->refill = fbgrow_refill;
78 b->spout = fbgrow_spout;
79 b->seek = fbgrow_seek;
80 b->close = fbgrow_close;
81 b->can_overwrite_buffer = 1;
86 fbgrow_reset(struct fastbuf *b)
88 b->bptr = b->bstop = b->buffer;
90 FB_GBUF(b)->last_written = NULL;
94 fbgrow_rewind(struct fastbuf *b)
96 if (!FB_GBUF(b)->last_written)
98 /* Last operation was a write, so remember the end position */
99 FB_GBUF(b)->last_written = b->bptr;
102 b->bstop = FB_GBUF(b)->last_written;
103 b->pos = b->bstop - b->buffer;
113 f = fbgrow_create(3);
114 for (uns i=0; i<5; i++)
117 bwrite(f, "12345", 5);
118 bwrite(f, "12345", 5);
119 printf("<%d>", (int)btell(f));
121 printf("<%d>", (int)btell(f));
123 printf("<%d>", (int)btell(f));
124 while ((t = bgetc(f)) >= 0)
126 printf("<%d>", (int)btell(f));
128 bseek(f, -1, SEEK_END);
129 printf("<%d>", (int)btell(f));
130 while ((t = bgetc(f)) >= 0)
132 printf("<%d>\n", (int)btell(f));