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 "ucw/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, ucw_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 + (ucw_off_t)b->size) /* <=, because we need to be able to seek just after file end */
115 f->buffer = f->bstop = b->data;
116 f->bptr = b->data + (pos - b->pos);
117 f->bufend = b->data + b->size;
119 FB_MEM(f)->block = b;
123 if (!m->first && !pos)
125 /* Seeking to offset 0 in an empty file needs an exception */
126 f->buffer = f->bptr = f->bstop = f->bufend = NULL;
128 FB_MEM(f)->block = NULL;
131 bthrow(f, "fb.seek", "fbmem_seek to invalid offset");
135 fbmem_close(struct fastbuf *f)
137 struct memstream *m = FB_MEM(f)->stream;
153 fbmem_create(unsigned blocksize)
155 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
156 struct memstream *s = xmalloc_zero(sizeof(struct memstream));
158 s->blocksize = blocksize;
161 FB_MEM(f)->stream = s;
162 f->name = "<fbmem-write>";
163 f->spout = fbmem_spout;
164 f->close = fbmem_close;
169 fbmem_clone_read(struct fastbuf *b)
171 struct fastbuf *f = xmalloc_zero(sizeof(struct fb_mem));
172 struct memstream *s = FB_MEM(b)->stream;
177 FB_MEM(f)->stream = s;
178 f->name = "<fbmem-read>";
179 f->refill = fbmem_refill;
180 f->seek = fbmem_seek;
181 f->close = fbmem_close;
182 f->can_overwrite_buffer = 1;
190 struct fastbuf *w, *r;
194 r = fbmem_clone_read(w);
195 bwrite(w, "12345", 5);
196 bwrite(w, "12345", 5);
197 printf("<%d>", (int)btell(w));
199 printf("<%d>", (int)btell(w));
200 printf("<%d>", (int)btell(r));
201 while ((t = bgetc(r)) >= 0)
203 printf("<%d>", (int)btell(r));
204 bwrite(w, "12345", 5);
205 bwrite(w, "12345", 5);
206 printf("<%d>", (int)btell(w));
209 printf("<!%d>", (int)btell(r));
210 while ((t = bgetc(r)) >= 0)
213 printf("<!%d>", (int)btell(r));
214 while ((t = bgetc(r)) >= 0)