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;
34 #define FB_MEM(f) ((struct fb_mem *)(f)->is_fastbuf)
37 fbmem_refill(struct fastbuf *f)
39 struct memstream *s = FB_MEM(f)->stream;
40 struct msblock *b = FB_MEM(f)->block;
48 else if (f->buffer == b->data && f->bstop < b->data + b->size)
50 f->bstop = b->data + b->size;
51 f->pos = b->pos + b->size;
60 f->buffer = f->bptr = b->data;
61 f->bufend = f->bstop = b->data + b->size;
62 f->pos = b->pos + b->size;
68 fbmem_spout(struct fastbuf *f)
70 struct memstream *s = FB_MEM(f)->stream;
71 struct msblock *b = FB_MEM(f)->block;
76 b->size = f->bptr - b->data;
77 if (b->size < s->blocksize)
80 bb = xmalloc(sizeof(struct msblock) + s->blocksize);
84 bb->pos = b->pos + b->size;
93 f->buffer = f->bptr = f->bstop = bb->data;
94 f->bufend = bb->data + s->blocksize;
96 FB_MEM(f)->block = bb;
100 fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence)
102 struct memstream *m = FB_MEM(f)->stream;
105 ASSERT(whence == SEEK_SET || whence == SEEK_END);
106 if (whence == SEEK_END)
108 for (b=m->first; b; b=b->next)
111 /* Yes, this is linear. But considering the average number of buckets, it doesn't matter. */
112 for (b=m->first; b; b=b->next)
114 if (pos <= b->pos + (sh_off_t)b->size) /* <=, because we need to be able to seek just after file end */
117 f->bptr = b->data + (pos - b->pos);
118 f->bufend = f->bstop = b->data + b->size;
119 f->pos = b->pos + b->size;
120 FB_MEM(f)->block = b;
124 if (!m->first && !pos)
126 /* Seeking to offset 0 in an empty file needs an exception */
127 f->buffer = f->bptr = f->bufend = NULL;
129 FB_MEM(f)->block = NULL;
132 die("fbmem_seek to invalid offset");
136 fbmem_close(struct fastbuf *f)
138 struct memstream *m = FB_MEM(f)->stream;
154 fbmem_create(unsigned blocksize)
156 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
157 struct memstream *s = xmalloc_zero(sizeof(struct memstream));
159 s->blocksize = blocksize;
162 FB_MEM(f)->stream = s;
163 f->name = "<fbmem-write>";
164 f->spout = fbmem_spout;
165 f->close = fbmem_close;
170 fbmem_clone_read(struct fastbuf *b)
172 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
173 struct memstream *s = FB_MEM(b)->stream;
178 FB_MEM(f)->stream = s;
179 f->name = "<fbmem-read>";
180 f->refill = fbmem_refill;
181 f->seek = fbmem_seek;
182 f->close = fbmem_close;
183 f->can_overwrite_buffer = 1;
191 struct fastbuf *w, *r;
195 r = fbmem_clone_read(w);
196 bwrite(w, "12345", 5);
197 bwrite(w, "12345", 5);
198 printf("<%d>", (int)btell(w));
200 printf("<%d>", (int)btell(w));
201 printf("<%d>", (int)btell(r));
202 while ((t = bgetc(r)) >= 0)
204 printf("<%d>", (int)btell(r));
205 bwrite(w, "12345", 5);
206 bwrite(w, "12345", 5);
207 printf("<%d>", (int)btell(w));
210 printf("<!%d>", (int)btell(r));
211 while ((t = bgetc(r)) >= 0)
214 printf("<!%d>", (int)btell(r));
215 while ((t = bgetc(r)) >= 0)