summaryrefslogtreecommitdiff
path: root/fitz/filt_basic.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-07-29 23:17:46 +0000
committerTor Andersson <tor@ghostscript.com>2010-07-29 23:17:46 +0000
commitd797d4707564bd9c0e1536d1d6355945aa1be740 (patch)
treeb6aef992de0ce2aa306c4dd330512852c1a63ede /fitz/filt_basic.c
parent0b954421d7908c8b835d96b4a945418c2ae08de7 (diff)
downloadmupdf-d797d4707564bd9c0e1536d1d6355945aa1be740.tar.xz
Use chained reader like interface for filters instead of process interface.
Diffstat (limited to 'fitz/filt_basic.c')
-rw-r--r--fitz/filt_basic.c624
1 files changed, 312 insertions, 312 deletions
diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c
index b9ec347e..90be39ee 100644
--- a/fitz/filt_basic.c
+++ b/fitz/filt_basic.c
@@ -1,97 +1,51 @@
#include "fitz.h"
-/* Identity filter */
+/* Pretend we have a filter that just copies data forever */
-fz_filter *
-fz_newcopyfilter(void)
+fz_stream *
+fz_opencopy(fz_stream *chain)
{
- FZ_NEWFILTER(fz_filter, f, copyfilter);
- return f;
+ return fz_keepstream(chain);
}
-void
-fz_dropcopyfilter(fz_filter *f)
-{
-}
-
-fz_error
-fz_processcopyfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out)
-{
- int n;
-
- while (1)
- {
- if (in->rp + 1 > in->wp)
- {
- if (in->eof)
- return fz_iodone;
- return fz_ioneedin;
- }
-
- if (out->wp + 1 > out->ep)
- return fz_ioneedout;
-
- n = MIN(in->wp - in->rp, out->ep - out->wp);
- if (n)
- {
- memcpy(out->wp, in->rp, n);
- in->rp += n;
- out->wp += n;
- }
- }
-}
-
-/* Null filter copies data until a specified length */
-
-typedef struct fz_nullfilter_s fz_nullfilter;
+/* Null filter copies a specified amount of data */
-struct fz_nullfilter_s
+struct nullfilter
{
- fz_filter super;
- int len;
- int cur;
+ fz_stream *chain;
+ int remain;
};
-fz_filter *
-fz_newnullfilter(int len)
+static int
+readnull(fz_stream *stm, unsigned char *buf, int len)
{
- FZ_NEWFILTER(fz_nullfilter, f, nullfilter);
- f->len = len;
- f->cur = 0;
- return (fz_filter *)f;
+ struct nullfilter *state = stm->state;
+ int amount = MIN(len, state->remain);
+ int n = fz_read(state->chain, buf, amount);
+ if (n < 0)
+ return fz_rethrow(n, "read error in null filter");
+ state->remain -= n;
+ return n;
}
-void
-fz_dropnullfilter(fz_filter *f)
+static void
+closenull(fz_stream *stm)
{
+ struct nullfilter *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
}
-fz_error
-fz_processnullfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out)
+fz_stream *
+fz_opennull(fz_stream *chain, int len)
{
- fz_nullfilter *f = (fz_nullfilter*)filter;
- int n;
-
- n = MIN(in->wp - in->rp, out->ep - out->wp);
- if (f->len >= 0)
- n = MIN(n, f->len - f->cur);
-
- if (n)
- {
- memcpy(out->wp, in->rp, n);
- in->rp += n;
- out->wp += n;
- f->cur += n;
- }
+ struct nullfilter *state;
- if (f->cur == f->len)
- return fz_iodone;
- if (in->rp == in->wp)
- return fz_ioneedin;
- if (out->wp == out->ep)
- return fz_ioneedout;
+ state = fz_malloc(sizeof(struct nullfilter));
+ state->chain = chain;
+ state->remain = len;
- return fz_throw("braindead programmer trapped in nullfilter");
+ return fz_newstream(state, readnull, closenull);
}
/* ASCII Hex Decode */
@@ -100,9 +54,8 @@ typedef struct fz_ahxd_s fz_ahxd;
struct fz_ahxd_s
{
- fz_filter super;
- int odd;
- int a;
+ fz_stream *chain;
+ int eod;
};
static inline int iswhite(int a)
@@ -133,58 +86,71 @@ static inline int fromhex(int a)
return 0;
}
-fz_filter *
-fz_newahxd(fz_obj *params)
-{
- FZ_NEWFILTER(fz_ahxd, f, ahxd);
- f->odd = 0;
- f->a = 0;
- return (fz_filter *)f;
-}
-
-void
-fz_dropahxd(fz_filter *f)
+static int
+readahxd(fz_stream *stm, unsigned char *buf, int len)
{
-}
+ fz_ahxd *state = stm->state;
+ unsigned char *p = buf;
+ int a, b, c, odd;
-fz_error
-fz_processahxd(fz_filter *filter, fz_buffer *in, fz_buffer *out)
-{
- fz_ahxd *f = (fz_ahxd*)filter;
- int b, c;
+ odd = 0;
- while (1)
+ while (p < buf + len)
{
- if (in->rp == in->wp)
- return fz_ioneedin;
+ if (state->eod)
+ return p - buf;
- if (out->wp == out->ep)
- return fz_ioneedout;
+ c = fz_readbyte(state->chain);
+ if (c < 0)
+ return p - buf;
- c = *in->rp++;
-
- if (ishex(c)) {
- if (!f->odd) {
- f->a = fromhex(c);
- f->odd = 1;
+ if (ishex(c))
+ {
+ if (!odd)
+ {
+ a = fromhex(c);
+ odd = 1;
}
- else {
+ else
+ {
b = fromhex(c);
- *out->wp++ = (f->a << 4) | b;
- f->odd = 0;
+ *p++ = (a << 4) | b;
+ odd = 0;
}
}
-
- else if (c == '>') {
- if (f->odd)
- *out->wp++ = (f->a << 4);
- return fz_iodone;
+ else if (c == '>')
+ {
+ if (odd)
+ *p++ = (a << 4);
+ state->eod = 1;
}
-
- else if (!iswhite(c)) {
+ else if (!iswhite(c))
+ {
return fz_throw("bad data in ahxd: '%c'", c);
}
}
+
+ return p - buf;
+}
+
+static void
+closeahxd(fz_stream *stm)
+{
+ fz_ahxd *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
+}
+
+fz_stream *
+fz_openahxd(fz_stream *chain)
+{
+ fz_ahxd *state;
+
+ state = fz_malloc(sizeof(fz_ahxd));
+ state->chain = chain;
+ state->eod = 0;
+
+ return fz_newstream(state, readahxd, closeahxd);
}
/* ASCII 85 Decode */
@@ -193,187 +159,207 @@ typedef struct fz_a85d_s fz_a85d;
struct fz_a85d_s
{
- fz_filter super;
- unsigned long word;
- int count;
+ fz_stream *chain;
+ unsigned char buf[4];
+ int remain;
+ int eod;
};
-fz_filter *
-fz_newa85d(fz_obj *params)
-{
- FZ_NEWFILTER(fz_a85d, f, a85d);
- f->word = 0;
- f->count = 0;
- return (fz_filter *)f;
-}
-
-void
-fz_dropa85d(fz_filter *f)
-{
-}
-
-fz_error
-fz_processa85d(fz_filter *filter, fz_buffer *in, fz_buffer *out)
+static int
+reada85d(fz_stream *stm, unsigned char *buf, int len)
{
- fz_a85d *f = (fz_a85d*)filter;
+ fz_a85d *state = stm->state;
+ unsigned char *p = buf;
+ int count = 0;
+ int word = 0;
int c;
- while (1)
- {
- if (in->rp == in->wp)
- return fz_ioneedin;
+ while (state->remain > 0 && p < buf + len)
+ *p++ = state->buf[4 - state->remain];
- c = *in->rp++;
+ while (p < buf + len)
+ {
+ if (state->eod)
+ return p - buf;
- if (c >= '!' && c <= 'u') {
- if (f->count == 4) {
- if (out->wp + 4 > out->ep) {
- in->rp --;
- return fz_ioneedout;
- }
+ c = fz_readbyte(state->chain);
+ if (c < 0)
+ return p - buf;
- f->word = f->word * 85 + (c - '!');
+ if (c >= '!' && c <= 'u')
+ {
+ if (count == 4)
+ {
+ word = word * 85 + (c - '!');
- *out->wp++ = (f->word >> 24) & 0xff;
- *out->wp++ = (f->word >> 16) & 0xff;
- *out->wp++ = (f->word >> 8) & 0xff;
- *out->wp++ = (f->word) & 0xff;
+ state->buf[0] = (word >> 24) & 0xff;
+ state->buf[1] = (word >> 16) & 0xff;
+ state->buf[2] = (word >> 8) & 0xff;
+ state->buf[3] = (word) & 0xff;
+ state->remain = 4;
- f->word = 0;
- f->count = 0;
+ word = 0;
+ count = 0;
}
- else {
- f->word = f->word * 85 + (c - '!');
- f->count ++;
+ else
+ {
+ word = word * 85 + (c - '!');
+ count ++;
}
}
- else if (c == 'z' && f->count == 0) {
- if (out->wp + 4 > out->ep) {
- in->rp --;
- return fz_ioneedout;
- }
- *out->wp++ = 0;
- *out->wp++ = 0;
- *out->wp++ = 0;
- *out->wp++ = 0;
+ else if (c == 'z' && count == 0)
+ {
+ state->buf[0] = 0;
+ state->buf[1] = 0;
+ state->buf[2] = 0;
+ state->buf[3] = 0;
+ state->remain = 4;
}
- else if (c == '~') {
- if (in->rp == in->wp) {
- in->rp --;
- return fz_ioneedin;
- }
-
- c = *in->rp++;
-
- if (c != '>') {
+ else if (c == '~')
+ {
+ c = fz_readbyte(state->chain);
+ if (c != '>')
return fz_throw("bad eod marker in a85d");
- }
-
- if (out->wp + f->count - 1 > out->ep) {
- in->rp -= 2;
- return fz_ioneedout;
- }
- switch (f->count) {
+ switch (count) {
case 0:
break;
case 1:
return fz_throw("partial final byte in a85d");
case 2:
- f->word = f->word * (85L * 85 * 85) + 0xffffffL;
- goto o1;
+ word = word * (85 * 85 * 85) + 0xffffff;
+ state->buf[0] = word >> 24;
+ state->remain = 1;
+ break;
case 3:
- f->word = f->word * (85L * 85) + 0xffffL;
- goto o2;
+ word = word * (85 * 85) + 0xffff;
+ state->buf[0] = word >> 24;
+ state->buf[1] = word >> 16;
+ state->remain = 2;
+ break;
case 4:
- f->word = f->word * 85 + 0xffL;
- *(out->wp+2) = f->word >> 8;
- o2: *(out->wp+1) = f->word >> 16;
- o1: *(out->wp+0) = f->word >> 24;
- out->wp += f->count - 1;
+ word = word * 85 + 0xff;
+ state->buf[0] = word >> 24;
+ state->buf[1] = word >> 16;
+ state->buf[2] = word >> 8;
+ state->remain = 3;
break;
}
- return fz_iodone;
+ state->eod = 1;
}
- else if (!iswhite(c)) {
+ else if (!iswhite(c))
+ {
return fz_throw("bad data in a85d: '%c'", c);
}
+
+ while (state->remain > 0 && p < buf + len)
+ *p++ = state->buf[4 - state->remain];
}
-}
-/* Run Length Decode */
+ return p - buf;
+}
-fz_filter *
-fz_newrld(fz_obj *params)
+static void
+closea85d(fz_stream *stm)
{
- FZ_NEWFILTER(fz_filter, f, rld);
- return f;
+ fz_a85d *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
}
-void
-fz_droprld(fz_filter *rld)
+fz_stream *
+fz_opena85d(fz_stream *chain)
{
+ fz_a85d *state;
+
+ state = fz_malloc(sizeof(fz_a85d));
+ state->chain = chain;
+ state->remain = 0;
+ state->eod = 0;
+
+ return fz_newstream(state, reada85d, closea85d);
}
-fz_error
-fz_processrld(fz_filter *filter, fz_buffer *in, fz_buffer *out)
+/* Run Length Decode */
+
+typedef struct fz_rld_s fz_rld;
+
+struct fz_rld_s
+{
+ fz_stream *chain;
+ int run, n, c;
+};
+
+static int
+readrld(fz_stream *stm, unsigned char *buf, int len)
{
- int run, i;
- unsigned char c;
+ fz_rld *state = stm->state;
+ unsigned char *p = buf;
- while (1)
+ while (p < buf + len)
{
- if (in->rp == in->wp)
+ if (state->run == 128)
+ return p - buf;
+
+ if (state->n == 0)
{
- if (in->eof)
+ state->run = fz_readbyte(state->chain);
+ if (state->run < 0)
+ state->run = 128;
+ if (state->run < 128)
+ state->n = state->run + 1;
+ if (state->run > 128)
{
- return fz_iodone;
+ state->n = 257 - state->run;
+ state->c = fz_readbyte(state->chain);
+ if (state->c < 0)
+ return fz_throw("premature end of data in run length decode");
}
- return fz_ioneedin;
}
- if (out->wp == out->ep)
- return fz_ioneedout;
-
- run = *in->rp++;
-
- if (run == 128)
+ if (state->run < 128)
{
- return fz_iodone;
- }
-
- else if (run < 128) {
- run = run + 1;
- if (in->rp + run > in->wp) {
- in->rp --;
- return fz_ioneedin;
- }
- if (out->wp + run > out->ep) {
- in->rp --;
- return fz_ioneedout;
+ while (p < buf + len && state->n--)
+ {
+ int c = fz_readbyte(state->chain);
+ if (c < 0)
+ return fz_throw("premature end of data in run length decode");
+ *p++ = c;
}
- for (i = 0; i < run; i++)
- *out->wp++ = *in->rp++;
}
- else if (run > 128) {
- run = 257 - run;
- if (in->rp + 1 > in->wp) {
- in->rp --;
- return fz_ioneedin;
- }
- if (out->wp + run > out->ep) {
- in->rp --;
- return fz_ioneedout;
- }
- c = *in->rp++;
- for (i = 0; i < run; i++)
- *out->wp++ = c;
+ if (state->run > 128)
+ {
+ while (p < buf + len && state->n--)
+ *p++ = state->c;
}
}
+
+ return p - buf;
+}
+
+static void
+closerld(fz_stream *stm)
+{
+ fz_rld *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
+}
+
+fz_stream *
+fz_openrld(fz_stream *chain)
+{
+ fz_rld *state;
+
+ state = fz_malloc(sizeof(fz_rld));
+ state->run = 0;
+ state->n = 0;
+ state->c = 0;
+
+ return fz_newstream(state, readrld, closerld);
}
/* RC4 Filter */
@@ -382,44 +368,43 @@ typedef struct fz_arc4c_s fz_arc4c;
struct fz_arc4c_s
{
- fz_filter super;
+ fz_stream *chain;
fz_arc4 arc4;
};
-fz_filter *
-fz_newarc4filter(unsigned char *key, unsigned keylen)
+static int
+readarc4(fz_stream *stm, unsigned char *buf, int len)
{
- FZ_NEWFILTER(fz_arc4c, f, arc4filter);
- fz_arc4init(&f->arc4, key, keylen);
- return (fz_filter *)f;
+ fz_arc4c *state = stm->state;
+ int n;
+
+ n = fz_read(state->chain, buf, len);
+ if (n < 0)
+ return fz_rethrow(n, "read error in arc4 filter");
+
+ fz_arc4encrypt(&state->arc4, buf, buf, n);
+
+ return n;
}
-void
-fz_droparc4filter(fz_filter *f)
+static void
+closearc4(fz_stream *stm)
{
+ fz_arc4c *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
}
-fz_error
-fz_processarc4filter(fz_filter *filter, fz_buffer *in, fz_buffer *out)
+fz_stream *
+fz_openarc4(fz_stream *chain, unsigned char *key, unsigned keylen)
{
- fz_arc4c *f = (fz_arc4c*)filter;
- int n;
+ fz_arc4c *state;
- while (1)
- {
- if (in->rp + 1 > in->wp) {
- if (in->eof)
- return fz_iodone;
- return fz_ioneedin;
- }
- if (out->wp + 1 > out->ep)
- return fz_ioneedout;
+ state = fz_malloc(sizeof(fz_arc4c));
+ state->chain = chain;
+ fz_arc4init(&state->arc4, key, keylen);
- n = MIN(in->wp - in->rp, out->ep - out->wp);
- fz_arc4encrypt(&f->arc4, out->wp, in->rp, n);
- in->rp += n;
- out->wp += n;
- }
+ return fz_newstream(state, readarc4, closearc4);
}
/* AES Filter */
@@ -428,65 +413,80 @@ typedef struct fz_aesd_s fz_aesd;
struct fz_aesd_s
{
- fz_filter super;
+ fz_stream *chain;
fz_aes aes;
unsigned char iv[16];
int ivcount;
+ unsigned char buf[16];
+ int remain;
};
-fz_filter *
-fz_newaesdfilter(unsigned char *key, unsigned keylen)
+static int
+readaesd(fz_stream *stm, unsigned char *buf, int len)
{
- FZ_NEWFILTER(fz_aesd, f, aesdfilter);
- aes_setkey_dec(&f->aes, key, keylen * 8);
- f->ivcount = 0;
- return (fz_filter *)f;
-}
+ fz_aesd *state = stm->state;
+ unsigned char *p = buf;
-void
-fz_dropaesdfilter(fz_filter *f)
-{
-}
+ while (state->ivcount < 16)
+ {
+ int c = fz_readbyte(state->chain);
+ if (c < 0)
+ return fz_throw("premature end in AES filter");
+ state->iv[state->ivcount++] = c;
+ }
-fz_error
-fz_processaesdfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out)
-{
- fz_aesd *f = (fz_aesd*)filter;
- int n;
+ while (p < buf + len && state->remain-- > 0)
+ *p++ = state->buf[16 - state->remain];
- while (1)
+ while (p < buf + len)
{
- if (in->rp + 16 > in->wp)
+ while (state->remain < 16)
{
- if (in->eof)
- return fz_iodone;
- return fz_ioneedin;
+ int c = fz_readbyte(state->chain);
+ if (c < 0)
+ {
+ if (state->remain > 0)
+ return fz_throw("premature end in AES filter");
+ return p - buf;
+ }
+ state->buf[state->remain++] = c;
}
- if (f->ivcount < 16)
+ aes_crypt_cbc(&state->aes, AES_DECRYPT, 16, state->iv, state->buf, state->buf);
+
+ /* strip padding at end of file */
+ if (fz_peekbyte(state->chain) == EOF)
{
- f->iv[f->ivcount++] = *in->rp++;
+ int pad = state->buf[15];
+ if (pad < 1 || pad > 16)
+ return fz_throw("aes padding out of range: %d", pad);
+ state->remain -= pad;
}
- else
- {
- if (out->wp + 16 > out->ep)
- return fz_ioneedout;
- n = MIN(in->wp - in->rp, out->ep - out->wp);
- n = (n / 16) * 16;
+ while (p < buf + len && state->remain-- > 0)
+ *p++ = state->buf[16 - state->remain];
+ }
- aes_crypt_cbc(&f->aes, AES_DECRYPT, n, f->iv, in->rp, out->wp);
- in->rp += n;
- out->wp += n;
+ return p - buf;
+}
- /* Remove padding bytes */
- if (in->eof && in->rp == in->wp)
- {
- int pad = out->wp[-1];
- if (pad < 1 || pad > 16)
- return fz_throw("aes padding out of range: %d", pad);
- out->wp -= pad;
- }
- }
- }
+static void
+closeaesd(fz_stream *stm)
+{
+ fz_aesd *state = stm->state;
+ fz_close(state->chain);
+ fz_free(state);
+}
+
+fz_stream *
+fz_openaesd(fz_stream *chain, unsigned char *key, unsigned keylen)
+{
+ fz_aesd *state;
+
+ state = fz_malloc(sizeof(fz_aesd));
+ state->chain = chain;
+ aes_setkey_dec(&state->aes, key, keylen * 8);
+ state->ivcount = 0;
+
+ return fz_newstream(state, readaesd, closeaesd);
}