2 * Sherlock Library -- Fast Buffered I/O on Memory Streams
4 * (c) 1997--2002 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"
18 struct msblock *first;
30 struct memstream *stream;
31 struct msblock *block;
33 #define FB_MEM(f) ((struct fb_mem *)(f)->is_fastbuf)
36 fbmem_refill(struct fastbuf *f)
38 struct memstream *s = FB_MEM(f)->stream;
39 struct msblock *b = FB_MEM(f)->block;
47 else if (f->buffer == b->data && f->bstop < b->data + b->size)
49 f->bstop = b->data + b->size;
50 f->pos = b->pos + b->size;
59 f->buffer = f->bptr = b->data;
60 f->bufend = f->bstop = b->data + b->size;
61 f->pos = b->pos + b->size;
67 fbmem_spout(struct fastbuf *f)
69 struct memstream *s = FB_MEM(f)->stream;
70 struct msblock *b = FB_MEM(f)->block;
75 b->size = f->bptr - b->data;
76 if (b->size < s->blocksize)
79 bb = xmalloc(sizeof(struct msblock) + s->blocksize);
83 bb->pos = b->pos + b->size;
92 f->buffer = f->bptr = f->bstop = bb->data;
93 f->bufend = bb->data + s->blocksize;
95 FB_MEM(f)->block = bb;
99 fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence)
101 struct memstream *m = FB_MEM(f)->stream;
104 ASSERT(whence == SEEK_SET || whence == SEEK_END);
105 if (whence == SEEK_END)
107 for (b=m->first; b; b=b->next)
110 /* Yes, this is linear. But considering the average number of buckets, it doesn't matter. */
111 for (b=m->first; b; b=b->next)
113 if (pos <= b->pos + (sh_off_t)b->size) /* <=, because we need to be able to seek just after file end */
116 f->bptr = b->data + (pos - b->pos);
117 f->bufend = f->bstop = b->data + b->size;
118 f->pos = b->pos + b->size;
119 FB_MEM(f)->block = b;
123 die("fbmem_seek to invalid offset");
127 fbmem_close(struct fastbuf *f)
129 struct memstream *m = FB_MEM(f)->stream;
145 fbmem_create(unsigned blocksize)
147 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
148 struct memstream *s = xmalloc_zero(sizeof(struct memstream));
150 s->blocksize = blocksize;
153 FB_MEM(f)->stream = s;
154 f->name = "<fbmem-write>";
155 f->spout = fbmem_spout;
156 f->close = fbmem_close;
161 fbmem_clone_read(struct fastbuf *b)
163 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
164 struct memstream *s = FB_MEM(b)->stream;
169 FB_MEM(f)->stream = s;
170 f->name = "<fbmem-read>";
171 f->refill = fbmem_refill;
172 f->seek = fbmem_seek;
173 f->close = fbmem_close;
181 struct fastbuf *w, *r;
185 r = fbmem_clone_read(w);
186 bwrite(w, "12345", 5);
187 bwrite(w, "12345", 5);
188 printf("<%d>", (int)btell(w));
190 printf("<%d>", (int)btell(w));
191 printf("<%d>", (int)btell(r));
192 while ((t = bgetc(r)) >= 0)
194 printf("<%d>", (int)btell(r));
195 bwrite(w, "12345", 5);
196 bwrite(w, "12345", 5);
197 printf("<%d>", (int)btell(w));
200 printf("<!%d>", (int)btell(r));
201 while ((t = bgetc(r)) >= 0)
204 printf("<!%d>", (int)btell(r));
205 while ((t = bgetc(r)) >= 0)