X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Ffb-grow.c;h=25f521ec5dc424de32541843848031c41b6f2164;hb=1e5ae8a779b693d8023ce9821b839f29e210d9e8;hp=e1da0107f4bfadc07118b1620603476819d92037;hpb=a4fe009d3366b0a3e119713b0ecc7fc0070efdfa;p=libucw.git diff --git a/ucw/fb-grow.c b/ucw/fb-grow.c index e1da0107..25f521ec 100644 --- a/ucw/fb-grow.c +++ b/ucw/fb-grow.c @@ -7,101 +7,117 @@ * of the GNU Lesser General Public License. */ -#include "ucw/lib.h" -#include "ucw/fastbuf.h" +#include +#include +#include #include #include struct fb_gbuf { struct fastbuf fb; - byte *last_written; + struct mempool *mp; + byte *end; }; -#define FB_GBUF(f) ((struct fb_gbuf *)(f)->is_fastbuf) +#define FB_GBUF(f) ((struct fb_gbuf *)(f)) -static int -fbgrow_refill(struct fastbuf *b) +static int fbgrow_refill(struct fastbuf *b) { - if (b->bstop != FB_GBUF(b)->last_written) - { - /* There was an intervening flush */ - b->bstop = FB_GBUF(b)->last_written; - b->pos = b->bstop - b->buffer; - return 1; - } - /* We are at the end */ - return 0; + b->bstop = FB_GBUF(b)->end; + b->pos = b->bstop - b->buffer; + return b->bstop > b->bptr; } -static void -fbgrow_spout(struct fastbuf *b) +static void fbgrow_spout(struct fastbuf *b) { - if (b->bptr >= b->bufend) + if (b->bptr == b->bufend) { - uns len = b->bufend - b->buffer; - b->buffer = xrealloc(b->buffer, 2*len); - b->bufend = b->buffer + 2*len; - b->bstop = b->buffer; - b->bptr = b->buffer + len; + uint len = b->bufend - b->buffer; + if (FB_GBUF(b)->mp) + { + byte *old = b->buffer; + b->buffer = mp_alloc(FB_GBUF(b)->mp, 2 * len); + memcpy(b->buffer, old, len); + } + else + b->buffer = xrealloc(b->buffer, 2 * len); + b->bufend = b->buffer + 2 * len; + FB_GBUF(b)->end = b->bptr = b->buffer + len; } + else if (FB_GBUF(b)->end < b->bptr) + FB_GBUF(b)->end = b->bptr; + b->bstop = b->buffer; + b->pos = 0; } -static int -fbgrow_seek(struct fastbuf *b, ucw_off_t pos, int whence) +static int fbgrow_seek(struct fastbuf *b, ucw_off_t pos, int whence) { - ASSERT(FB_GBUF(b)->last_written); /* Seeks allowed only in read mode */ - ucw_off_t len = FB_GBUF(b)->last_written - b->buffer; + ucw_off_t len = FB_GBUF(b)->end - b->buffer; if (whence == SEEK_END) pos += len; - ASSERT(pos >= 0 && pos <= len); + if (pos < 0 || pos > len) + bthrow(b, "seek", "Seek out of range"); b->bptr = b->buffer + pos; - b->bstop = FB_GBUF(b)->last_written; - b->pos = len; + b->bstop = b->buffer; + b->pos = 0; return 1; } -static void -fbgrow_close(struct fastbuf *b) +static void fbgrow_close(struct fastbuf *b) { xfree(b->buffer); xfree(b); } -struct fastbuf * -fbgrow_create(unsigned basic_size) +struct fastbuf *fbgrow_create_mp(struct mempool *mp, uint basic_size) { - struct fastbuf *b = xmalloc_zero(sizeof(struct fb_gbuf)); - b->buffer = xmalloc(basic_size); + ASSERT(basic_size); + struct fastbuf *b; + if (mp) + { + b = mp_alloc_zero(mp, sizeof(struct fb_gbuf)); + b->buffer = mp_alloc(mp, basic_size); + FB_GBUF(b)->mp = mp; + } + else + { + b = xmalloc_zero(sizeof(struct fb_gbuf)); + b->buffer = xmalloc(basic_size); + b->close = fbgrow_close; + } b->bufend = b->buffer + basic_size; b->bptr = b->bstop = b->buffer; b->name = ""; b->refill = fbgrow_refill; b->spout = fbgrow_spout; b->seek = fbgrow_seek; - b->close = fbgrow_close; b->can_overwrite_buffer = 1; return b; } -void -fbgrow_reset(struct fastbuf *b) +struct fastbuf *fbgrow_create(uint basic_size) { - b->bptr = b->bstop = b->buffer; + return fbgrow_create_mp(NULL, basic_size); +} + +void fbgrow_reset(struct fastbuf *b) +{ + FB_GBUF(b)->end = b->bptr = b->bstop = b->buffer; b->pos = 0; - FB_GBUF(b)->last_written = NULL; } -void -fbgrow_rewind(struct fastbuf *b) +void fbgrow_rewind(struct fastbuf *b) { - if (!FB_GBUF(b)->last_written) - { - /* Last operation was a write, so remember the end position */ - FB_GBUF(b)->last_written = b->bptr; - } - b->bptr = b->buffer; - b->bstop = FB_GBUF(b)->last_written; - b->pos = b->bstop - b->buffer; + brewind(b); +} + +uint fbgrow_get_buf(struct fastbuf *b, byte **buf) +{ + byte *end = FB_GBUF(b)->end; + end = MAX(end, b->bptr); + if (buf) + *buf = b->buffer; + return end - b->buffer; } #ifdef TEST @@ -109,10 +125,10 @@ fbgrow_rewind(struct fastbuf *b) int main(void) { struct fastbuf *f; - uns t; + uint t; f = fbgrow_create(3); - for (uns i=0; i<5; i++) + for (uint i=0; i<5; i++) { fbgrow_reset(f); bwrite(f, "12345", 5);