summaryrefslogtreecommitdiff
path: root/source/fitz/filter-flate.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2013-06-19 15:29:44 +0200
committerTor Andersson <tor.andersson@artifex.com>2013-06-20 16:45:35 +0200
commit0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch)
tree3d65d820d9fdba2d0d394d99c36290c851b78ca0 /source/fitz/filter-flate.c
parent1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff)
downloadmupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz
Rearrange source files.
Diffstat (limited to 'source/fitz/filter-flate.c')
-rw-r--r--source/fitz/filter-flate.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/source/fitz/filter-flate.c b/source/fitz/filter-flate.c
new file mode 100644
index 00000000..73451d59
--- /dev/null
+++ b/source/fitz/filter-flate.c
@@ -0,0 +1,117 @@
+#include "mupdf/fitz.h"
+
+#include <zlib.h>
+
+typedef struct fz_flate_s fz_flate;
+
+struct fz_flate_s
+{
+ fz_stream *chain;
+ z_stream z;
+};
+
+static void *zalloc(void *opaque, unsigned int items, unsigned int size)
+{
+ return fz_malloc_array_no_throw(opaque, items, size);
+}
+
+static void zfree(void *opaque, void *ptr)
+{
+ fz_free(opaque, ptr);
+}
+
+static int
+read_flated(fz_stream *stm, unsigned char *outbuf, int outlen)
+{
+ fz_flate *state = stm->state;
+ fz_stream *chain = state->chain;
+ z_streamp zp = &state->z;
+ int code;
+
+ zp->next_out = outbuf;
+ zp->avail_out = outlen;
+
+ while (zp->avail_out > 0)
+ {
+ if (chain->rp == chain->wp)
+ fz_fill_buffer(chain);
+
+ zp->next_in = chain->rp;
+ zp->avail_in = chain->wp - chain->rp;
+
+ code = inflate(zp, Z_SYNC_FLUSH);
+
+ chain->rp = chain->wp - zp->avail_in;
+
+ if (code == Z_STREAM_END)
+ {
+ return outlen - zp->avail_out;
+ }
+ else if (code == Z_BUF_ERROR)
+ {
+ fz_warn(stm->ctx, "premature end of data in flate filter");
+ return outlen - zp->avail_out;
+ }
+ else if (code == Z_DATA_ERROR && zp->avail_in == 0)
+ {
+ fz_warn(stm->ctx, "ignoring zlib error: %s", zp->msg);
+ return outlen - zp->avail_out;
+ }
+ else if (code != Z_OK)
+ {
+ fz_throw(stm->ctx, FZ_ERROR_GENERIC, "zlib error: %s", zp->msg);
+ }
+ }
+
+ return outlen - zp->avail_out;
+}
+
+static void
+close_flated(fz_context *ctx, void *state_)
+{
+ fz_flate *state = (fz_flate *)state_;
+ int code;
+
+ code = inflateEnd(&state->z);
+ if (code != Z_OK)
+ fz_warn(ctx, "zlib error: inflateEnd: %s", state->z.msg);
+
+ fz_close(state->chain);
+ fz_free(ctx, state);
+}
+
+fz_stream *
+fz_open_flated(fz_stream *chain)
+{
+ fz_flate *state = NULL;
+ int code = Z_OK;
+ fz_context *ctx = chain->ctx;
+
+ fz_var(code);
+ fz_var(state);
+
+ fz_try(ctx)
+ {
+ state = fz_malloc_struct(ctx, fz_flate);
+ state->chain = chain;
+
+ state->z.zalloc = zalloc;
+ state->z.zfree = zfree;
+ state->z.opaque = ctx;
+ state->z.next_in = NULL;
+ state->z.avail_in = 0;
+
+ code = inflateInit(&state->z);
+ if (code != Z_OK)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "zlib error: inflateInit: %s", state->z.msg);
+ }
+ fz_catch(ctx)
+ {
+ if (state && code == Z_OK)
+ inflateEnd(&state->z);
+ fz_free(ctx, state);
+ fz_close(chain);
+ fz_rethrow(ctx);
+ }
+ return fz_new_stream(ctx, state, read_flated, close_flated);
+}