diff options
Diffstat (limited to 'fitz/filt_flate.c')
-rw-r--r-- | fitz/filt_flate.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/fitz/filt_flate.c b/fitz/filt_flate.c new file mode 100644 index 00000000..6a86da3a --- /dev/null +++ b/fitz/filt_flate.c @@ -0,0 +1,208 @@ +#include "fitz-base.h" +#include "fitz-stream.h" + +#include <zlib.h> + +typedef struct fz_flate_s fz_flate; + +struct fz_flate_s +{ + fz_filter super; + z_stream z; +}; + +static void * +zmalloc(void *opaque, unsigned int items, unsigned int size) +{ + return fz_malloc(items * size); +} + +fz_error * +fz_newflated(fz_filter **fp, fz_obj *params) +{ + fz_error *eo; + fz_obj *obj; + int zipfmt; + int ei; + + FZ_NEWFILTER(fz_flate, f, flated); + + f->z.zalloc = zmalloc; + f->z.zfree = (void(*)(void*,void*))fz_currentmemorycontext()->free; + f->z.opaque = fz_currentmemorycontext(); + f->z.next_in = nil; + f->z.avail_in = 0; + + zipfmt = 0; + + if (params) + { + obj = fz_dictgets(params, "ZIP"); + if (obj) zipfmt = fz_tobool(obj); + } + + if (zipfmt) + { + /* if windowbits is negative the zlib header is skipped */ + ei = inflateInit2(&f->z, -15); + } + else + ei = inflateInit(&f->z); + + if (ei != Z_OK) + { + eo = fz_throw("zlib error: inflateInit: %s", f->z.msg); + fz_free(f); + return eo; + } + + return fz_okay; +} + +void +fz_dropflated(fz_filter *f) +{ + z_streamp zp = &((fz_flate*)f)->z; + int err; + + err = inflateEnd(zp); + if (err != Z_OK) + fprintf(stderr, "inflateEnd: %s", zp->msg); +} + +fz_error * +fz_processflated(fz_filter *f, fz_buffer *in, fz_buffer *out) +{ + z_streamp zp = &((fz_flate*)f)->z; + int err; + + if (in->rp == in->wp && !in->eof) + return fz_ioneedin; + if (out->wp == out->ep) + return fz_ioneedout; + + zp->next_in = in->rp; + zp->avail_in = in->wp - in->rp; + + zp->next_out = out->wp; + zp->avail_out = out->ep - out->wp; + + err = inflate(zp, Z_NO_FLUSH); + + in->rp = in->wp - zp->avail_in; + out->wp = out->ep - zp->avail_out; + + if (err == Z_STREAM_END || err == Z_BUF_ERROR) + { + return fz_iodone; + } + else if (err == Z_OK) + { + if (in->rp == in->wp && !in->eof) + return fz_ioneedin; + if (out->wp == out->ep) + return fz_ioneedout; + return fz_ioneedin; /* hmm, what's going on here? */ + } + else + { + return fz_throw("zlib error: inflate: %s", zp->msg); + } +} + +fz_error * +fz_newflatee(fz_filter **fp, fz_obj *params) +{ + fz_obj *obj; + fz_error *eo; + int effort; + int zipfmt; + int ei; + + FZ_NEWFILTER(fz_flate, f, flatee); + + effort = -1; + zipfmt = 0; + + if (params) + { + obj = fz_dictgets(params, "Effort"); + if (obj) effort = fz_toint(obj); + obj = fz_dictgets(params, "ZIP"); + if (obj) zipfmt = fz_tobool(obj); + } + + f->z.zalloc = zmalloc; + f->z.zfree = (void(*)(void*,void*))fz_currentmemorycontext()->free; + f->z.opaque = fz_currentmemorycontext(); + f->z.next_in = nil; + f->z.avail_in = 0; + + if (zipfmt) + ei = deflateInit2(&f->z, effort, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + else + ei = deflateInit(&f->z, effort); + + if (ei != Z_OK) + { + eo = fz_throw("zlib error: deflateInit: %s", f->z.msg); + fz_free(f); + return eo; + } + + return fz_okay; +} + +void +fz_dropflatee(fz_filter *f) +{ + z_streamp zp = &((fz_flate*)f)->z; + int err; + + err = deflateEnd(zp); + if (err != Z_OK) + fprintf(stderr, "deflateEnd: %s", zp->msg); + + fz_free(f); +} + +fz_error * +fz_processflatee(fz_filter *f, fz_buffer *in, fz_buffer *out) +{ + z_streamp zp = &((fz_flate*)f)->z; + int err; + + if (in->rp == in->wp && !in->eof) + return fz_ioneedin; + if (out->wp == out->ep) + return fz_ioneedout; + + zp->next_in = in->rp; + zp->avail_in = in->wp - in->rp; + + zp->next_out = out->wp; + zp->avail_out = out->ep - out->wp; + + err = deflate(zp, in->eof ? Z_FINISH : Z_NO_FLUSH); + + in->rp = in->wp - zp->avail_in; + out->wp = out->ep - zp->avail_out; + + if (err == Z_STREAM_END) + { + return fz_iodone; + } + else if (err == Z_OK) + { + if (in->rp == in->wp && !in->eof) + return fz_ioneedin; + if (out->wp == out->ep) + return fz_ioneedout; + return fz_ioneedin; /* hmm? */ + } + else + { + return fz_throw("zlib error: deflate: %s", zp->msg); + } +} + |