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 <ucw/fastbuf.h>
12 #include <ucw/mempool.h>
22 #define FB_GBUF(f) ((struct fb_gbuf *)(f))
24 static int fbgrow_refill(struct fastbuf *b)
26 b->bstop = FB_GBUF(b)->end;
27 b->pos = b->bstop - b->buffer;
28 return b->bstop > b->bptr;
31 static void fbgrow_spout(struct fastbuf *b)
33 if (b->bptr == b->bufend)
35 uint len = b->bufend - b->buffer;
38 byte *old = b->buffer;
39 b->buffer = mp_alloc(FB_GBUF(b)->mp, 2 * len);
40 memcpy(b->buffer, old, len);
43 b->buffer = xrealloc(b->buffer, 2 * len);
44 b->bufend = b->buffer + 2 * len;
45 FB_GBUF(b)->end = b->bptr = b->buffer + len;
47 else if (FB_GBUF(b)->end < b->bptr)
48 FB_GBUF(b)->end = b->bptr;
53 static int fbgrow_seek(struct fastbuf *b, ucw_off_t pos, int whence)
55 ucw_off_t len = FB_GBUF(b)->end - b->buffer;
56 if (whence == SEEK_END)
58 if (pos < 0 || pos > len)
59 bthrow(b, "seek", "Seek out of range");
60 b->bptr = b->buffer + pos;
66 static void fbgrow_close(struct fastbuf *b)
72 struct fastbuf *fbgrow_create_mp(struct mempool *mp, uint basic_size)
78 b = mp_alloc_zero(mp, sizeof(struct fb_gbuf));
79 b->buffer = mp_alloc(mp, basic_size);
84 b = xmalloc_zero(sizeof(struct fb_gbuf));
85 b->buffer = xmalloc(basic_size);
86 b->close = fbgrow_close;
88 b->bufend = b->buffer + basic_size;
89 b->bptr = b->bstop = b->buffer;
90 FB_GBUF(b)->end = b->buffer;
92 b->refill = fbgrow_refill;
93 b->spout = fbgrow_spout;
94 b->seek = fbgrow_seek;
95 b->can_overwrite_buffer = 1;
99 struct fastbuf *fbgrow_create(uint basic_size)
101 return fbgrow_create_mp(NULL, basic_size);
104 void fbgrow_reset(struct fastbuf *b)
106 FB_GBUF(b)->end = b->bptr = b->bstop = b->buffer;
110 void fbgrow_rewind(struct fastbuf *b)
115 uint fbgrow_get_buf(struct fastbuf *b, byte **buf)
117 byte *end = FB_GBUF(b)->end;
118 end = MAX(end, b->bptr);
121 return end - b->buffer;
131 f = fbgrow_create(3);
132 for (uint i=0; i<5; i++)
135 bwrite(f, "12345", 5);
136 bwrite(f, "12345", 5);
137 printf("<%d>", (int)btell(f));
139 printf("<%d>", (int)btell(f));
141 printf("<%d>", (int)btell(f));
142 while ((t = bgetc(f)) != ~0U)
144 printf("<%d>", (int)btell(f));
146 bseek(f, -1, SEEK_END);
147 printf("<%d>", (int)btell(f));
148 while ((t = bgetc(f)) != ~0U)
150 printf("<%d>\n", (int)btell(f));