2 * Sherlock Library -- Fast Buffered I/O on Memory Streams
4 * (c) 1997--2002 Martin Mares <mj@ucw.cz>
5 * (c) 2004 Robert Spalek <robert@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
12 #include "lib/fastbuf.h"
19 struct msblock *first;
31 struct memstream *stream;
32 struct msblock *block;
35 #define FB_MEM(f) ((struct fb_mem *)(f)->is_fastbuf)
38 fbmem_refill(struct fastbuf *f)
40 struct memstream *s = FB_MEM(f)->stream;
41 struct msblock *b = FB_MEM(f)->block;
49 else if (f->buffer == b->data && f->bstop < b->data + b->size)
51 f->bstop = b->data + b->size;
52 f->pos = b->pos + b->size;
61 f->buffer = f->bptr = b->data;
62 f->bufend = f->bstop = b->data + b->size;
63 f->pos = b->pos + b->size;
69 fbmem_spout(struct fastbuf *f)
71 struct memstream *s = FB_MEM(f)->stream;
72 struct msblock *b = FB_MEM(f)->block;
77 b->size = f->bptr - b->data;
78 if (b->size < s->blocksize)
81 bb = xmalloc(sizeof(struct msblock) + s->blocksize);
85 bb->pos = b->pos + b->size;
94 f->buffer = f->bptr = f->bstop = bb->data;
95 f->bufend = bb->data + s->blocksize;
97 FB_MEM(f)->block = bb;
101 fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence)
103 struct memstream *m = FB_MEM(f)->stream;
106 ASSERT(whence == SEEK_SET || whence == SEEK_END);
107 if (whence == SEEK_END)
109 for (b=m->first; b; b=b->next)
112 /* Yes, this is linear. But considering the average number of buckets, it doesn't matter. */
113 for (b=m->first; b; b=b->next)
115 if (pos <= b->pos + (sh_off_t)b->size) /* <=, because we need to be able to seek just after file end */
118 f->bptr = b->data + (pos - b->pos);
119 f->bufend = f->bstop = b->data + b->size;
120 f->pos = b->pos + b->size;
121 FB_MEM(f)->block = b;
125 if (!m->first && !pos)
127 /* Seeking to offset 0 in an empty file needs an exception */
128 f->buffer = f->bptr = f->bufend = NULL;
130 FB_MEM(f)->block = NULL;
133 die("fbmem_seek to invalid offset");
137 fbmem_close(struct fastbuf *f)
139 struct memstream *m = FB_MEM(f)->stream;
155 fbmem_config(struct fastbuf *f, uns item, int value)
159 case BCONFIG_CAN_OVERWRITE: ;
160 int old_value = FB_MEM(f)->can_overwrite;
161 if (value >= 0 && value <= 1)
162 FB_MEM(f)->can_overwrite = value;
170 fbmem_create(unsigned blocksize)
172 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
173 struct memstream *s = xmalloc_zero(sizeof(struct memstream));
175 s->blocksize = blocksize;
178 FB_MEM(f)->stream = s;
179 f->name = "<fbmem-write>";
180 f->spout = fbmem_spout;
181 f->close = fbmem_close;
182 f->config = fbmem_config;
187 fbmem_clone_read(struct fastbuf *b)
189 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
190 struct memstream *s = FB_MEM(b)->stream;
195 FB_MEM(f)->stream = s;
196 f->name = "<fbmem-read>";
197 f->refill = fbmem_refill;
198 f->seek = fbmem_seek;
199 f->close = fbmem_close;
200 f->config = fbmem_config;
201 FB_MEM(f)->can_overwrite = 1;
209 struct fastbuf *w, *r;
213 r = fbmem_clone_read(w);
214 bwrite(w, "12345", 5);
215 bwrite(w, "12345", 5);
216 printf("<%d>", (int)btell(w));
218 printf("<%d>", (int)btell(w));
219 printf("<%d>", (int)btell(r));
220 while ((t = bgetc(r)) >= 0)
222 printf("<%d>", (int)btell(r));
223 bwrite(w, "12345", 5);
224 bwrite(w, "12345", 5);
225 printf("<%d>", (int)btell(w));
228 printf("<!%d>", (int)btell(r));
229 while ((t = bgetc(r)) >= 0)
232 printf("<!%d>", (int)btell(r));
233 while ((t = bgetc(r)) >= 0)