2 * UCW Library -- Fast Buffered I/O on itself
4 * (c) 2012 Jan Moskyto Matejka <mq@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/clists.h>
12 #include <ucw/fastbuf.h>
13 #include <ucw/mempool.h>
24 #define FB_MULTI(f) ((struct fb_multi *)(f))
31 #define SUBBUF(f) ((struct subbuf *)(f))
34 fbmulti_subbuf_get_end(struct subbuf *s)
37 bseek(s->fb, 0, SEEK_END);
38 s->end = s->begin + btell(s->fb);
43 fbmulti_subbuf_next(struct fastbuf *f)
45 struct subbuf* next = clist_next(FB_MULTI(f)->subbufs, &FB_MULTI(f)->cur->n);
50 bseek(FB_MULTI(f)->cur->fb, 0, SEEK_SET);
51 next->begin = FB_MULTI(f)->cur->end;
54 FB_MULTI(f)->cur = next;
59 fbmulti_refill(struct fastbuf *f)
61 if (f->bufend == f->bstop)
62 f->bptr = f->bstop = f->buffer;
63 uns len = bread(FB_MULTI(f)->cur->fb, f->bstop, (f->bufend - f->bstop));
69 // Current buf returned EOF
70 // Update the information on end of this buffer
71 fbmulti_subbuf_get_end(FB_MULTI(f)->cur);
73 // Take the next one if exists
74 if (fbmulti_subbuf_next(f))
75 return fbmulti_refill(f);
81 fbmulti_get_len(struct fastbuf *f)
86 CLIST_FOR_EACH(struct subbuf *, n, *(FB_MULTI(f)->subbufs))
88 n->begin = FB_MULTI(f)->len;
89 fbmulti_subbuf_get_end(n);
90 FB_MULTI(f)->len = n->end;
95 fbmulti_seek(struct fastbuf *f, ucw_off_t pos, int whence)
101 FB_MULTI(f)->cur = clist_head(FB_MULTI(f)->subbufs);
102 FB_MULTI(f)->cur->begin = 0;
104 return fbmulti_seek(f, pos, SEEK_SET);
108 fbmulti_subbuf_get_end(FB_MULTI(f)->cur);
109 if (pos < FB_MULTI(f)->cur->end)
112 if (!fbmulti_subbuf_next(f))
113 bthrow(f, "seek", "Seek out of range");
117 bseek(FB_MULTI(f)->cur->fb, (pos - FB_MULTI(f)->cur->begin), SEEK_SET);
119 f->bptr = f->bstop = f->buffer;
125 return fbmulti_seek(f, FB_MULTI(f)->len+pos, SEEK_CUR);
134 fbmulti_update_capability(struct fastbuf *f) {
135 // FB Multi is only a proxy to other fastbufs ... if any of them lacks
136 // support of any feature, FB Multi also provides no support of that feature
137 f->refill = fbmulti_refill;
138 f->seek = fbmulti_seek;
140 CLIST_FOR_EACH(struct subbuf *, n, *(FB_MULTI(f)->subbufs)) {
150 fbmulti_create(uns bufsize, ...)
152 struct mempool *mp = mp_new(bufsize);
153 struct fastbuf *fb_out = mp_alloc(mp, sizeof(struct fb_multi));
154 FB_MULTI(fb_out)->mp = mp;
156 struct fastbuf *fb_in;
157 clist* subbufs = mp_alloc(mp, sizeof(clist));
159 FB_MULTI(fb_out)->subbufs = subbufs;
162 va_start(args, bufsize);
163 while (fb_in = va_arg(args, struct fastbuf *)) {
164 struct subbuf *sb = mp_alloc(mp, sizeof(struct subbuf));
166 clist_add_tail(subbufs, &(sb->n));
170 FB_MULTI(fb_out)->cur = clist_head(subbufs);
172 fb_out->buffer = mp_alloc(mp, bufsize);
173 fb_out->bptr = fb_out->bstop = fb_out->buffer;
174 fb_out->bufend = fb_out->buffer + bufsize;
175 fb_out->name = "<multi>";
177 fbmulti_update_capability(fb_out);
184 int main(int argc, char ** argv)
188 fprintf(stderr, "You must specify a test (r, w, o)\n");
195 char *data[] = { "One\nLine", "Two\nLines", "Th\nreeLi\nnes\n" };
196 struct fastbuf fb[ARRAY_SIZE(data)];
197 for (uns i=0;i<ARRAY_SIZE(data);i++)
198 fbbuf_init_read(&fb[i], data[i], strlen(data[i]), 0);
200 struct fastbuf* f = fbmulti_create(4, &fb[0], &fb[1], &fb[2], NULL);
203 while (bgets(f, buffer, 9))
211 char *data[] = { "Mnl", "ige" };
212 struct fastbuf fb[ARRAY_SIZE(data)];
213 for (uns i=0;i<ARRAY_SIZE(data);i++)
214 fbbuf_init_read(&fb[i], data[i], strlen(data[i]), 0);
216 struct fastbuf* f = fbmulti_create(4, &fb[0], &fb[1], NULL);
218 int pos[] = {0, 3, 1, 4, 2, 5};
220 for (uns i=0;i<ARRAY_SIZE(pos);i++) {
221 bseek(f, pos[i], SEEK_SET);
230 char *data = "Insae";
231 struct fastbuf fb[4];
232 fbbuf_init_read(&fb[0], data, 1, 0);
233 fbbuf_init_read(&fb[1], data + 1, 1, 0);
234 fbbuf_init_read(&fb[2], data + 2, 2, 0);
235 fbbuf_init_read(&fb[3], data + 4, 1, 0);
237 struct fastbuf* f = fbmulti_create(8, &fb[0], &fb[1], &fb[2], &fb[1], &fb[3], NULL);
240 while(bgets(f, buffer, 9))