2 * UCW 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"
16 struct msblock *first;
28 struct memstream *stream;
29 struct msblock *block;
31 #define FB_MEM(f) ((struct fb_mem *)(f)->is_fastbuf)
34 fbmem_refill(struct fastbuf *f)
36 struct memstream *s = FB_MEM(f)->stream;
37 struct msblock *b = FB_MEM(f)->block;
45 else if (f->buffer == b->data && f->bstop < b->data + b->size)
47 f->bstop = b->data + b->size;
48 f->pos = b->pos + b->size;
57 f->buffer = f->bptr = b->data;
58 f->bufend = f->bstop = b->data + b->size;
59 f->pos = b->pos + b->size;
65 fbmem_spout(struct fastbuf *f)
67 struct memstream *s = FB_MEM(f)->stream;
68 struct msblock *b = FB_MEM(f)->block;
73 b->size = f->bptr - b->data;
74 if (b->size < s->blocksize)
77 bb = xmalloc(sizeof(struct msblock) + s->blocksize);
81 bb->pos = b->pos + b->size;
90 f->buffer = f->bptr = f->bstop = bb->data;
91 f->bufend = bb->data + s->blocksize;
93 FB_MEM(f)->block = bb;
97 fbmem_seek(struct fastbuf *f, sh_off_t pos, int whence)
99 struct memstream *m = FB_MEM(f)->stream;
102 ASSERT(whence == SEEK_SET || whence == SEEK_END);
103 if (whence == SEEK_END)
105 for (b=m->first; b; b=b->next)
108 /* Yes, this is linear. But considering the average number of buckets, it doesn't matter. */
109 for (b=m->first; b; b=b->next)
111 if (pos <= b->pos + (sh_off_t)b->size) /* <=, because we need to be able to seek just after file end */
114 f->bptr = b->data + (pos - b->pos);
115 f->bufend = f->bstop = b->data + b->size;
116 f->pos = b->pos + b->size;
117 FB_MEM(f)->block = b;
121 if (!m->first && !pos)
123 /* Seeking to offset 0 in an empty file needs an exception */
124 f->buffer = f->bptr = f->bufend = NULL;
126 FB_MEM(f)->block = NULL;
129 die("fbmem_seek to invalid offset");
133 fbmem_close(struct fastbuf *f)
135 struct memstream *m = FB_MEM(f)->stream;
151 fbmem_create(unsigned blocksize)
153 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
154 struct memstream *s = xmalloc_zero(sizeof(struct memstream));
156 s->blocksize = blocksize;
159 FB_MEM(f)->stream = s;
160 f->name = "<fbmem-write>";
161 f->spout = fbmem_spout;
162 f->close = fbmem_close;
167 fbmem_clone_read(struct fastbuf *b)
169 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
170 struct memstream *s = FB_MEM(b)->stream;
175 FB_MEM(f)->stream = s;
176 f->name = "<fbmem-read>";
177 f->refill = fbmem_refill;
178 f->seek = fbmem_seek;
179 f->close = fbmem_close;
180 f->can_overwrite_buffer = 1;
188 struct fastbuf *w, *r;
192 r = fbmem_clone_read(w);
193 bwrite(w, "12345", 5);
194 bwrite(w, "12345", 5);
195 printf("<%d>", (int)btell(w));
197 printf("<%d>", (int)btell(w));
198 printf("<%d>", (int)btell(r));
199 while ((t = bgetc(r)) >= 0)
201 printf("<%d>", (int)btell(r));
202 bwrite(w, "12345", 5);
203 bwrite(w, "12345", 5);
204 printf("<%d>", (int)btell(w));
207 printf("<!%d>", (int)btell(r));
208 while ((t = bgetc(r)) >= 0)
211 printf("<!%d>", (int)btell(r));
212 while ((t = bgetc(r)) >= 0)