diff options
Diffstat (limited to 'filter/filer.c')
-rw-r--r-- | filter/filer.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/filter/filer.c b/filter/filer.c new file mode 100644 index 00000000..804d7f7e --- /dev/null +++ b/filter/filer.c @@ -0,0 +1,237 @@ +#include <fitz.h> + +static int doread(fz_buffer *b, int fd) +{ + int n = read(fd, b->wp, b->ep - b->wp); + if (n == -1) + return -1; + if (n == 0) + b->eof = 1; + b->wp += n; + return n; +} + +static int producedata(fz_file *f) +{ + fz_error *reason; + int produced; + int n; + + assert(f->mode == O_RDONLY); + assert(f->error == nil); + + if (!f->filter) + { + fz_rewindbuffer(f->out); + n = doread(f->out, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in read: %s", strerror(errno)); + return -1; + } + return 0; + } + + produced = 0; + + while (1) + { + reason = fz_process(f->filter, f->in, f->out); + + if (f->filter->produced) + produced = 1; + + if (reason == fz_ioneedin) + { + if (f->in->eof) { + f->error = fz_throw("ioerror: premature eof in filter"); + return -1; + } + + /* no space to produce, rewind or grow */ + if (f->in->wp == f->in->ep) + { + if (f->in->rp > f->in->bp) + f->error = fz_rewindbuffer(f->in); + else + f->error = fz_growbuffer(f->in); + if (f->error) + return -1; + } + + /* then fill with more input */ + n = doread(f->in, f->fd); + if (n < 0) { + f->error = fz_throw("ioerror in read: %s", strerror(errno)); + return -1; + } + + if (produced) + return 0; + } + + else if (reason == fz_ioneedout) + { + if (produced) + return 0; + + /* need more outspace, and produced no data */ + if (f->out->rp > f->out->bp) + f->error = fz_rewindbuffer(f->out); + else + f->error = fz_growbuffer(f->out); + if (f->error) + return -1; + } + + else if (reason == fz_iodone) + return 0; + + else { + f->error = reason; + return -1; + } + } +} + +int +fz_peekbyte(fz_file *f) +{ + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return EOF; + if (producedata(f)) return EOF; + } + + if (f->out->rp < f->out->wp) + return *f->out->rp; + + return EOF; +} + +int +fz_readbyte(fz_file *f) +{ + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return EOF; + if (producedata(f)) return EOF; + } + + if (f->out->rp < f->out->wp) + return *f->out->rp++; + + return EOF; +} + +int +fz_read(fz_file *f, char *buf, int n) +{ + int i = 0; + + while (i < n) + { + while (f->out->rp < f->out->wp && i < n) + buf[i++] = *f->out->rp ++; + + if (f->out->rp == f->out->wp) + { + if (f->out->eof) return i; + if (producedata(f) < 0) return -1; + } + } + + return i; +} + +int +fz_readline(fz_file *f, char *buf, int n) +{ + int c = EOF; + char *s = buf; + + while (n > 1) + { + c = fz_readbyte(f); + if (c == EOF) + break; + if (c == '\r') { + c = fz_peekbyte(f); + if (c == '\n') + c = fz_readbyte(f); + break; + } + if (c == '\n') + break; + *s++ = c; + n--; + } + if (n) + *s = '\0'; + return s - buf; +} + +/* + * Utility function to consume contents of file stream into + * a freshly allocated buffer; realloced and trimmed to size. + */ + +enum { CHUNKSIZE = 4096 }; + +fz_error * +fz_readfile(unsigned char **bufp, int *lenp, fz_file *file) +{ + unsigned char *newbuf; + unsigned char *buf; + int len; + int pos; + int n; + + *bufp = nil; + *lenp = 0; + + len = 0; + pos = 0; + buf = nil; + + while (1) + { + if (len - pos == 0) + { + len += CHUNKSIZE; + newbuf = fz_realloc(buf, len); + if (!newbuf) + { + fz_free(buf); + return fz_outofmem; + } + buf = newbuf; + } + + n = fz_read(file, buf + pos, len - pos); + +printf("fz_read %d bytes\n", n); + + if (n < 0) + { + fz_free(buf); + return fz_ferror(file); + } + + pos += n; + + if (n < CHUNKSIZE) + { + newbuf = fz_realloc(buf, pos); + if (!newbuf) + { + fz_free(buf); + return fz_outofmem; + } + + *bufp = newbuf; + *lenp = pos; + return nil; + } + } +} + |