summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile10
-rw-r--r--filter/buffer.c27
-rw-r--r--filter/file.c589
-rw-r--r--filter/filec.c302
-rw-r--r--filter/filer.c237
-rw-r--r--filter/filew.c235
-rw-r--r--include/fitz/file.h11
-rw-r--r--include/fitz/filter.h2
-rw-r--r--include/fitz/object.h6
-rw-r--r--mupdf/cmap.c2
-rw-r--r--mupdf/font.c2
-rw-r--r--mupdf/pagetree.c4
-rw-r--r--mupdf/save.c9
-rw-r--r--mupdf/xref.c2
-rw-r--r--object/print.c83
-rw-r--r--test/pdfdebug.c (renamed from test/mupdf.c)12
-rw-r--r--tree/debug.c2
17 files changed, 862 insertions, 673 deletions
diff --git a/Jamfile b/Jamfile
index 6e335c98..3d21bbe7 100644
--- a/Jamfile
+++ b/Jamfile
@@ -33,7 +33,9 @@ Library libfitz :
# filter
filter/buffer.c
filter/filter.c
- filter/file.c # unistd.h
+ filter/filec.c # unistd.h
+ filter/filer.c # unistd.h
+ filter/filew.c # unistd.h
filter/null.c
filter/arc4filter.c
@@ -118,8 +120,10 @@ LINKLIBS =
-lm
;
-Main t-mupdf : test/mupdf.c ;
-LinkLibraries t-mupdf : libmupdf libfitz ;
+Main pdfclean : test/pdfclean.c ;
+Main pdfdebug : test/pdfdebug.c ;
+
+LinkLibraries pdfclean pdfdebug : libmupdf libfitz ;
#Main t-filter : tests/t-filter.c ;
#Main t-parse : tests/t-parse.c ;
diff --git a/filter/buffer.c b/filter/buffer.c
index 7b728b9b..25e30a55 100644
--- a/filter/buffer.c
+++ b/filter/buffer.c
@@ -8,6 +8,7 @@ fz_newbuffer(fz_buffer **bp, int size)
b = *bp = fz_malloc(sizeof(fz_buffer));
if (!b) return fz_outofmem;
+ b->ownsdata = 1;
b->bp = fz_malloc(size);
if (!b->bp) { fz_free(b); return fz_outofmem; }
@@ -19,10 +20,31 @@ fz_newbuffer(fz_buffer **bp, int size)
return nil;
}
+fz_error *
+fz_newbufferwithdata(fz_buffer **bp, unsigned char *data, int size)
+{
+ fz_buffer *b;
+
+ b = *bp = fz_malloc(sizeof(fz_buffer));
+ if (!b) return fz_outofmem;
+
+ b->ownsdata = 0;
+ b->bp = data;
+
+ b->rp = b->bp;
+ b->wp = b->bp;
+ b->ep = b->bp + size;
+ b->eof = 0;
+
+ return nil;
+}
+
+
void
fz_freebuffer(fz_buffer *buf)
{
- fz_free(buf->bp);
+ if (buf->ownsdata)
+ fz_free(buf->bp);
fz_free(buf);
}
@@ -35,6 +57,8 @@ fz_growbuffer(fz_buffer *buf)
int wp = buf->wp - buf->bp;
int ep = buf->ep - buf->bp;
+ assert(buf->ownsdata);
+
newbp = fz_realloc(buf->bp, ep * 2);
if (!newbp) return fz_outofmem;
@@ -49,6 +73,7 @@ fz_growbuffer(fz_buffer *buf)
fz_error *
fz_rewindbuffer(fz_buffer *buf)
{
+ assert(buf->ownsdata);
memmove(buf->bp, buf->rp, buf->wp - buf->rp);
buf->wp = buf->bp + (buf->wp - buf->rp);
buf->rp = buf->bp;
diff --git a/filter/file.c b/filter/file.c
deleted file mode 100644
index c3ab63a4..00000000
--- a/filter/file.c
+++ /dev/null
@@ -1,589 +0,0 @@
-#include <fitz.h>
-
-/* TODO: nil filter on write */
-
-fz_error *
-fz_ferror(fz_file *f)
-{
- fz_error *e = f->error;
- f->error = nil;
- return e;
-}
-
-fz_error *
-fz_openfile(fz_file **filep, char *path, int mode)
-{
- fz_error *error;
- fz_file *file;
- int fd;
-
- assert(mode == O_RDONLY || mode == O_WRONLY);
-
- file = *filep = fz_malloc(sizeof(fz_file));
- if (!file)
- return fz_outofmem;
-
- fd = open(path, mode, 0);
- if (fd == -1)
- return fz_throw("ioerror: open '%s': %s", path, strerror(errno));
-
- file->mode = mode;
- file->fd = fd;
- file->depth = 0;
- file->error = nil;
- file->filter = nil;
- file->in = nil;
- file->out = nil;
-
- error = fz_newbuffer(&file->in, FZ_BUFSIZE);
- if (error)
- goto cleanup;
-
- error = fz_newbuffer(&file->out, FZ_BUFSIZE);
- if (error)
- goto cleanup;
-
- return nil;
-
-cleanup:
- close(fd);
- fz_free(file->out);
- fz_free(file->in);
- fz_free(file);
- *filep = nil;
- return error;
-}
-
-void
-fz_closefile(fz_file *file)
-{
- assert(file->depth == 0);
-
- if (file->mode == O_WRONLY)
- fz_flush(file);
-
- if (file->error)
- {
- fz_warn("%s", file->error->msg);
- fz_freeerror(file->error);
- file->error = nil;
- }
-
- close(file->fd);
-
- if (file->filter) fz_freefilter(file->filter);
- fz_freebuffer(file->in);
- fz_freebuffer(file->out);
- fz_free(file);
-}
-
-fz_error *
-fz_pushfilter(fz_file *file, fz_filter *filter)
-{
- fz_error *error;
- fz_buffer *buf;
-
- if (file->depth == 0)
- {
- buf = file->out;
- file->out = file->in;
- file->in = buf;
-
- file->out->rp = file->out->bp;
- file->out->wp = file->out->bp;
- file->out->eof = 0;
-
- file->filter = filter;
- }
- else
- {
- error = fz_chainpipeline(&file->filter, file->filter, filter, file->out);
- if (error)
- return error;
-
- error = fz_newbuffer(&file->out, FZ_BUFSIZE);
- if (error)
- {
- fz_unchainpipeline(file->filter, &file->filter, &file->out);
- return error;
- }
- }
-
- file->depth ++;
-
- return nil;
-}
-
-void
-fz_popfilter(fz_file *file)
-{
- fz_buffer *buf;
-
- assert(file->depth > 0);
-
- if (file->mode == O_WRONLY)
- fz_flush(file);
-
- if (file->error)
- {
- fz_warn("%s", file->error->msg);
- fz_freeerror(file->error);
- file->error = nil;
- }
-
- if (file->depth == 1)
- {
- fz_freefilter(file->filter);
- file->filter = nil;
-
- buf = file->out;
- file->out = file->in;
- file->in = buf;
-
- file->in->rp = file->in->bp;
- file->in->wp = file->in->bp;
- file->in->eof = 0;
- }
- else
- {
- fz_freebuffer(file->out);
- fz_unchainpipeline(file->filter, &file->filter, &file->out);
- }
-
- file->depth --;
-}
-
-int
-fz_seek(fz_file *f, int ofs)
-{
- int t;
- int c;
-
- assert(f->mode == O_RDONLY);
-
- if (f->filter)
- {
- if (ofs < fz_tell(f))
- {
- f->error = fz_throw("ioerror: cannot seek backwards in filter");
- return -1;
- }
- while (fz_tell(f) < ofs)
- {
- c = fz_readbyte(f);
- if (c == EOF)
- return -1;
- }
- return 0;
- }
-
- t = lseek(f->fd, ofs, 0);
- if (t == -1)
- {
- f->error = fz_throw("ioerror: lseek: %s", strerror(errno));
- return -1;
- }
-
- f->out->rp = f->out->bp;
- f->out->wp = f->out->bp;
- f->out->eof = 0;
-
- return 0;
-}
-
-int
-fz_tell(fz_file *f)
-{
- int t;
-
- if (f->filter)
- {
- return f->filter->count - (f->out->wp - f->out->rp);
- }
-
- t = lseek(f->fd, 0, 1);
- if (t == -1)
- {
- f->error = fz_throw("ioerror: lseek: %s", strerror(errno));
- return -1;
- }
-
- return t - (f->out->wp - f->out->rp);
-}
-
-/*
- * Read mode
- */
-
-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;
-}
-
-/*
- * Write mode
- */
-
-static int dowrite(fz_buffer *b, int fd)
-{
- int n = write(fd, b->rp, b->wp - b->rp);
- if (n == -1)
- return -1;
- b->rp += n;
- return n;
-}
-
-int
-fz_write(fz_file *f, char *buf, int n)
-{
- fz_error *reason;
- int i = 0;
- int x;
-
- assert(f->mode == O_WRONLY);
- assert(f->error == nil);
-
- while (i < n)
- {
- while (f->in->rp < f->in->wp && i < n)
- {
- *f->in->rp++ = buf[i++];
- }
-
- if (f->in->rp == f->in->wp)
- {
- reason = fz_process(f->filter, f->in, f->out);
-
- if (reason == fz_ioneedin)
- {
- 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;
- }
- }
-
- else if (reason == fz_ioneedout)
- {
- x = dowrite(f->out, f->fd);
- if (x < 0) {
- f->error = fz_throw("ioerror in write: %s", strerror(errno));
- return -1;
- }
-
- 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)
- {
- x = dowrite(f->out, f->fd);
- if (x < 0) {
- f->error = fz_throw("ioerror in write: %s", strerror(errno));
- return -1;
- }
- break;
- }
-
- else {
- f->error = reason;
- return -1;
- }
- }
- }
-
- return i;
-}
-
-int
-fz_flush(fz_file *f)
-{
- fz_error *reason;
- int n;
-
- assert(f->mode == O_WRONLY);
- assert(f->error == nil);
-
- f->in->eof = 1;
-
- while (!f->out->eof)
- {
- reason = fz_process(f->filter, f->in, f->out);
-
- if (reason == fz_ioneedin) {
- f->error = fz_throw("ioerror: premature eof in filter");
- return -1;
- }
-
- else if (reason == fz_ioneedout)
- {
- n = dowrite(f->out, f->fd);
- if (n < 0) {
- f->error = fz_throw("ioerror in write: %s", strerror(errno));
- return -1;
- }
-
- 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)
- {
- n = dowrite(f->out, f->fd);
- if (n < 0) {
- f->error = fz_throw("ioerror in write: %s", strerror(errno));
- return -1;
- }
- break;
- }
-
- else {
- f->error = reason;
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- * 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;
- }
- }
-}
-
diff --git a/filter/filec.c b/filter/filec.c
new file mode 100644
index 00000000..f62d1265
--- /dev/null
+++ b/filter/filec.c
@@ -0,0 +1,302 @@
+#include <fitz.h>
+
+fz_error *
+fz_ferror(fz_file *f)
+{
+ fz_error *e = f->error;
+ f->error = nil;
+ return e;
+}
+
+fz_error *
+fz_openfile(fz_file **filep, char *path, int mode)
+{
+ fz_error *error;
+ fz_file *file;
+ int fd;
+
+ assert(mode == O_RDONLY || mode == O_WRONLY);
+
+ file = *filep = fz_malloc(sizeof(fz_file));
+ if (!file)
+ return fz_outofmem;
+
+ fd = open(path, mode, 0);
+ if (fd == -1)
+ return fz_throw("ioerror: open '%s': %s", path, strerror(errno));
+
+ file->mode = mode;
+ file->fd = fd;
+ file->depth = 0;
+ file->error = nil;
+ file->filter = nil;
+ file->in = nil;
+ file->out = nil;
+
+ error = fz_newbuffer(&file->in, FZ_BUFSIZE);
+ if (error)
+ goto cleanup;
+
+ error = fz_newbuffer(&file->out, FZ_BUFSIZE);
+ if (error)
+ goto cleanup;
+
+ return nil;
+
+cleanup:
+ *filep = nil;
+ close(fd);
+ fz_free(file->out);
+ fz_free(file->in);
+ fz_free(file);
+ return error;
+}
+
+fz_error *
+fz_openbuffer(fz_file **filep, fz_buffer *buf, int mode)
+{
+ fz_error *error;
+ fz_file *file;
+
+ assert(mode == O_RDONLY || mode == O_WRONLY);
+
+ file = *filep = fz_malloc(sizeof(fz_file));
+ if (!file)
+ return fz_outofmem;
+
+ file->mode = mode;
+ file->fd = -1;
+ file->depth = 0;
+ file->error = nil;
+ file->filter = nil;
+
+ if (mode == O_RDONLY)
+ {
+ file->in = buf;
+ error = fz_newbuffer(&file->out, FZ_BUFSIZE);
+ if (error)
+ goto cleanup;
+ }
+
+ else
+ {
+ error = fz_newbuffer(&file->in, FZ_BUFSIZE);
+ if (error)
+ goto cleanup;
+ file->out = buf;
+ }
+
+ return nil;
+
+cleanup:
+ *filep = nil;
+ fz_free(file);
+ return error;
+}
+
+void
+fz_closefile(fz_file *file)
+{
+ assert(file->depth == 0);
+
+ if (file->mode != O_RDONLY)
+ fz_flush(file);
+
+ if (file->error)
+ {
+ fz_warn("%s", file->error->msg);
+ fz_freeerror(file->error);
+ file->error = nil;
+ }
+
+ if (file->fd == -1) /* open to buffer not file */
+ {
+ if (file->mode == O_RDONLY)
+ fz_freebuffer(file->out);
+ else
+ fz_freebuffer(file->in);
+ }
+ else
+ {
+ fz_freebuffer(file->in);
+ fz_freebuffer(file->out);
+ close(file->fd);
+ }
+
+ if (file->filter)
+ fz_freefilter(file->filter);
+
+ fz_free(file);
+}
+
+fz_error *
+fz_pushfilter(fz_file *file, fz_filter *filter)
+{
+ fz_error *error;
+
+ /* without a filter, one buffer is ignored: unignore. */
+ if (file->depth == 0)
+ {
+ fz_buffer *buf;
+
+ buf = file->out;
+ file->out = file->in;
+ file->in = buf;
+
+// XXX
+ if (file->mode == O_RDONLY)
+ {
+ file->out->rp = file->out->bp;
+ file->out->wp = file->out->bp;
+ file->out->eof = 0;
+ }
+
+ file->filter = filter;
+ }
+
+ else
+ {
+ if (file->mode == O_RDONLY)
+ {
+ error = fz_chainpipeline(&file->filter, file->filter, filter, file->out);
+ if (error)
+ return error;
+
+ error = fz_newbuffer(&file->out, FZ_BUFSIZE);
+ if (error)
+ {
+ fz_unchainpipeline(file->filter, &file->filter, &file->out);
+ return error;
+ }
+ }
+
+ else
+ {
+ error = fz_chainpipeline(&file->filter, filter, file->filter, file->in);
+ if (error)
+ return error;
+
+ error = fz_newbuffer(&file->in, FZ_BUFSIZE);
+ if (error)
+ {
+ fz_unchainpipeline(file->filter, &file->filter, &file->in);
+ return error;
+ }
+ }
+ }
+
+ file->depth ++;
+
+ return nil;
+}
+
+void
+fz_popfilter(fz_file *file)
+{
+ fz_buffer *buf;
+
+ assert(file->depth > 0);
+
+ if (file->mode != O_RDONLY)
+ fz_flush(file);
+
+ if (file->error)
+ {
+ fz_warn("%s", file->error->msg);
+ fz_freeerror(file->error);
+ file->error = nil;
+ }
+
+ if (file->depth == 1)
+ {
+ fz_freefilter(file->filter);
+ file->filter = nil;
+
+ buf = file->out;
+ file->out = file->in;
+ file->in = buf;
+
+// XXX
+ file->in->rp = file->in->bp;
+ file->in->wp = file->in->bp;
+ file->in->eof = 0;
+ }
+ else
+ {
+ if (file->mode == O_RDONLY)
+ {
+ fz_freebuffer(file->out);
+ fz_unchainpipeline(file->filter, &file->filter, &file->out);
+ }
+ else
+ {
+ fz_freebuffer(file->in);
+ fz_unchainpipeline(file->filter, &file->filter, &file->in);
+ }
+ }
+
+ file->depth --;
+}
+
+int
+fz_seek(fz_file *f, int ofs)
+{
+ int t;
+ int c;
+
+ assert(f->mode == O_RDONLY);
+
+ if (f->filter)
+ {
+ if (ofs < fz_tell(f))
+ {
+ f->error = fz_throw("ioerror: cannot seek backwards in filter");
+ return -1;
+ }
+ while (fz_tell(f) < ofs)
+ {
+ c = fz_readbyte(f);
+ if (c == EOF)
+ return -1;
+ }
+ return 0;
+ }
+
+ t = lseek(f->fd, ofs, 0);
+ if (t == -1)
+ {
+ f->error = fz_throw("ioerror: lseek: %s", strerror(errno));
+ return -1;
+ }
+
+ f->out->rp = f->out->bp;
+ f->out->wp = f->out->bp;
+ f->out->eof = 0;
+
+ return 0;
+}
+
+int
+fz_tell(fz_file *f)
+{
+ int t;
+
+ if (f->filter)
+ {
+ assert(f->mode == O_RDONLY);
+ return f->filter->count - (f->out->wp - f->out->rp);
+ }
+
+ t = lseek(f->fd, 0, 1);
+ if (t == -1)
+ {
+ f->error = fz_throw("ioerror: lseek: %s", strerror(errno));
+ return -1;
+ }
+
+ if (f->mode == O_RDONLY)
+ return t - (f->out->wp - f->out->rp);
+ else
+ return t - (f->in->wp - f->in->rp);
+}
+
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;
+ }
+ }
+}
+
diff --git a/filter/filew.c b/filter/filew.c
new file mode 100644
index 00000000..0422e60e
--- /dev/null
+++ b/filter/filew.c
@@ -0,0 +1,235 @@
+#include <fitz.h>
+
+int
+fz_printstring(fz_file *f, char *s)
+{
+ return fz_write(f, s, strlen(s));
+}
+
+int
+fz_printobj(fz_file *file, fz_obj *obj, int tight)
+{
+ char buf[1024];
+ char *ptr;
+ int n;
+
+ n = fz_sprintobj(nil, 0, obj, tight);
+ if (n < sizeof buf)
+ {
+ fz_sprintobj(buf, sizeof buf, obj, tight);
+ return fz_write(file, buf, n);
+ }
+ else
+ {
+ ptr = fz_malloc(n);
+ if (!ptr) {
+ file->error = fz_outofmem;
+ return -1;
+ }
+ fz_sprintobj(ptr, n, obj, tight);
+ n = fz_write(file, buf, n);
+ fz_free(ptr);
+ return n;
+ }
+}
+
+int
+fz_print(fz_file *f, char *fmt, ...)
+{
+ va_list ap;
+ char buf[1024];
+ char *p;
+ int n;
+
+ va_start(ap, fmt);
+ n = vsnprintf(buf, sizeof buf, fmt, ap);
+ va_end(ap);
+
+ if (n < sizeof buf)
+ return fz_write(f, buf, n);
+
+ p = fz_malloc(n);
+ if (!p) {
+ f->error = fz_outofmem;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(p, n, fmt, ap);
+ va_end(ap);
+
+ n = fz_write(f, p, n);
+
+ fz_free(p);
+
+ return n;
+}
+
+static int dowrite(fz_buffer *b, int fd)
+{
+ int n = write(fd, b->rp, b->wp - b->rp);
+ if (n == -1)
+ return -1;
+ b->rp += n;
+ return n;
+}
+
+int
+fz_write(fz_file *f, char *buf, int n)
+{
+ fz_error *reason;
+ int i = 0;
+ int x;
+
+ assert(f->mode == O_WRONLY);
+ assert(f->error == nil);
+
+ if (!f->filter)
+ {
+ while (i < n)
+ {
+ while (f->in->wp < f->in->ep && i < n)
+ *f->in->wp++ = buf[i++];
+
+ if (f->in->wp == f->in->ep)
+ {
+ x = dowrite(f->in, f->fd);
+ if (x < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+
+ fz_rewindbuffer(f->in);
+ }
+ }
+
+ return 0;
+ }
+
+ while (i < n)
+ {
+ while (f->in->rp < f->in->wp && i < n)
+ {
+ *f->in->rp++ = buf[i++];
+ }
+
+ if (f->in->rp == f->in->wp)
+ {
+ reason = fz_process(f->filter, f->in, f->out);
+
+ if (reason == fz_ioneedin)
+ {
+ 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;
+ }
+ }
+
+ else if (reason == fz_ioneedout)
+ {
+ x = dowrite(f->out, f->fd);
+ if (x < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+
+ 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)
+ {
+ x = dowrite(f->out, f->fd);
+ if (x < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+ break;
+ }
+
+ else {
+ f->error = reason;
+ return -1;
+ }
+ }
+ }
+
+ return i;
+}
+
+int
+fz_flush(fz_file *f)
+{
+ fz_error *reason;
+ int n;
+
+ assert(f->mode == O_WRONLY);
+ assert(f->error == nil);
+
+ f->in->eof = 1;
+
+ if (!f->filter)
+ {
+ while (f->in->rp < f->in->wp)
+ {
+ n = dowrite(f->in, f->fd);
+ if (n < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ while (!f->out->eof)
+ {
+ reason = fz_process(f->filter, f->in, f->out);
+
+ if (reason == fz_ioneedin) {
+ f->error = fz_throw("ioerror: premature eof in filter");
+ return -1;
+ }
+
+ else if (reason == fz_ioneedout)
+ {
+ n = dowrite(f->out, f->fd);
+ if (n < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+
+ 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)
+ {
+ n = dowrite(f->out, f->fd);
+ if (n < 0) {
+ f->error = fz_throw("ioerror in write: %s", strerror(errno));
+ return -1;
+ }
+ break;
+ }
+
+ else {
+ f->error = reason;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/include/fitz/file.h b/include/fitz/file.h
index e687e572..7807570c 100644
--- a/include/fitz/file.h
+++ b/include/fitz/file.h
@@ -12,9 +12,11 @@ struct fz_file_s
};
fz_error *fz_openfile(fz_file **filep, char *path, int mode);
+fz_error *fz_openbuffer(fz_file **filep, fz_buffer *buf, int mode);
fz_error *fz_pushfilter(fz_file *file, fz_filter *filter);
void fz_popfilter(fz_file *file);
void fz_closefile(fz_file *file);
+fz_error *fz_ferror(fz_file *f);
int fz_seek(fz_file *f, int ofs);
int fz_tell(fz_file *f);
@@ -24,10 +26,11 @@ int fz_peekbyte(fz_file *f);
int fz_readline(fz_file *f, char *buf, int n);
int fz_read(fz_file *f, char *buf, int n);
-int fz_write(fz_file *f, char *buf, int n);
-int fz_flush(fz_file *f);
-
fz_error *fz_readfile(unsigned char **bufp, int *lenp, fz_file *file);
-fz_error *fz_ferror(fz_file *f);
+int fz_printstring(fz_file *f, char *s);
+int fz_printobj(fz_file *f, fz_obj *o, int tight);
+int fz_print(fz_file *f, char *fmt, ...);
+int fz_write(fz_file *f, char *buf, int n);
+int fz_flush(fz_file *f);
diff --git a/include/fitz/filter.h b/include/fitz/filter.h
index 6f234143..f6a1603f 100644
--- a/include/fitz/filter.h
+++ b/include/fitz/filter.h
@@ -35,6 +35,7 @@ struct fz_filter_s
struct fz_buffer_s
{
+ int ownsdata;
unsigned char *bp;
unsigned char *rp;
unsigned char *wp;
@@ -53,6 +54,7 @@ fz_error *fz_chainpipeline(fz_filter **fp, fz_filter *head, fz_filter *tail, fz_
void fz_unchainpipeline(fz_filter *pipe, fz_filter **oldfp, fz_buffer **oldbp);
fz_error *fz_newbuffer(fz_buffer **bufp, int size);
+fz_error *fz_newbufferwithdata(fz_buffer **bufp, unsigned char *data, int size);
fz_error *fz_rewindbuffer(fz_buffer *buf);
fz_error *fz_growbuffer(fz_buffer *buf);
void fz_freebuffer(fz_buffer *buf);
diff --git a/include/fitz/object.h b/include/fitz/object.h
index 8ccdd153..2a9ab15f 100644
--- a/include/fitz/object.h
+++ b/include/fitz/object.h
@@ -113,10 +113,8 @@ fz_error *fz_dictdel(fz_obj *dict, fz_obj *key);
fz_error *fz_dictdels(fz_obj *dict, char *key);
void fz_freedict(fz_obj *dict);
-int fz_sprintobj(char *s, fz_obj *obj);
-int fz_sprintcobj(char *s, fz_obj *obj);
-int fz_fprintobj(FILE *f, fz_obj *obj);
-int fz_fprintcobj(FILE *f, fz_obj *obj);
+int fz_sprintobj(char *s, int n, fz_obj *obj, int tight);
+void fz_debugobj(fz_obj *obj);
fz_error *fz_parseobj(fz_obj **objp, char *s);
fz_error *fz_packobj(fz_obj **objp, char *fmt, ...);
diff --git a/mupdf/cmap.c b/mupdf/cmap.c
index cec14e19..180e93c3 100644
--- a/mupdf/cmap.c
+++ b/mupdf/cmap.c
@@ -385,7 +385,7 @@ pdf_loadembeddedcmap(fz_cmap **cmapp, pdf_xref *xref, fz_obj *stmref)
return error;
printf(" embedded cmap: ");
-fz_fprintcobj(stdout, stmobj);
+fz_debugobj(stmobj);
printf("\n");
fflush(stdout);
diff --git a/mupdf/font.c b/mupdf/font.c
index 1fa5fa93..6d499c60 100644
--- a/mupdf/font.c
+++ b/mupdf/font.c
@@ -674,7 +674,7 @@ printf(" cidtogidmap %d\n", len / 2);
goto cleanup;
printf(" W2 ");
-fz_fprintobj(stdout, widths);
+fz_debugobj(widths);
printf("\n");
for (i = 0; i < fz_arraylen(widths); )
diff --git a/mupdf/pagetree.c b/mupdf/pagetree.c
index de500f18..6ddc07c9 100644
--- a/mupdf/pagetree.c
+++ b/mupdf/pagetree.c
@@ -87,9 +87,9 @@ pdf_debugpagetree(pdf_pagetree *pages)
printf("<<\n /Type /Pages\n /Count %d\n /Kids [\n", pages->count);
for (i = 0; i < pages->count; i++) {
printf(" ");
- fz_fprintobj(stdout, pages->pref[i]);
+ fz_debugobj(pages->pref[i]);
printf("\t%% page %d\n", i + 1);
- //fz_fprintobj(stdout, pages->pobj[i]);
+ //fz_debugobj(stdout, pages->pobj[i]);
//printf("\n");
}
printf(" ]\n>>\n");
diff --git a/mupdf/save.c b/mupdf/save.c
index c86c9e72..1698fc23 100644
--- a/mupdf/save.c
+++ b/mupdf/save.c
@@ -4,7 +4,6 @@
static fz_error *writestored(FILE *out, pdf_xref *xref, int oid)
{
pdf_xrefentry *x = xref->table + oid;
- fz_error *error;
fz_obj *obj;
fz_buffer *stm;
@@ -18,7 +17,7 @@ static fz_error *writestored(FILE *out, pdf_xref *xref, int oid)
pdf_cryptobj(xref->crypt, obj, oid, x->gen);
fprintf(out, "%d %d obj\n", oid, x->gen);
- fz_fprintobj(out, obj);
+ fz_debugobj(obj);
fprintf(out, "\n");
if (stm)
@@ -54,7 +53,7 @@ static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid)
return error;
fprintf(out, "%d %d obj\n", oid, x->gen);
- fz_fprintobj(out, obj);
+ fz_debugobj(obj);
fprintf(out, "\n");
if (stmofs != -1)
@@ -203,13 +202,13 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path)
obj = fz_dictgets(xref->trailer, "Encrypt");
if (obj) {
fprintf(out,"\n /Encrypt ");
- fz_fprintobj(out, obj);
+ fz_debugobj(obj);
}
obj = fz_dictgets(xref->trailer, "ID");
if (obj) {
fprintf(out,"\n /ID ");
- fz_fprintobj(out, obj);
+ fz_debugobj(obj);
}
fprintf(out, "\n>>\n\n");
diff --git a/mupdf/xref.c b/mupdf/xref.c
index 37cc16c2..53b9f239 100644
--- a/mupdf/xref.c
+++ b/mupdf/xref.c
@@ -117,7 +117,7 @@ pdf_debugxref(pdf_xref *xref)
xref->table[i].type);
}
printf("trailer\n");
- fz_fprintobj(stdout, xref->trailer);
+ fz_debugobj(xref->trailer);
printf("\n");
}
diff --git a/object/print.c b/object/print.c
index af6941f9..520e53b9 100644
--- a/object/print.c
+++ b/object/print.c
@@ -2,10 +2,9 @@
struct fmt
{
- FILE *file;
char *buf;
+ int cap;
int len;
-
int indent;
int tight;
int col;
@@ -33,9 +32,7 @@ static inline void fmtputc(struct fmt *fmt, int c)
}
fmt->sep = 0;
- if (fmt->file)
- putc(c, fmt->file);
- if (fmt->buf)
+ if (fmt->buf && fmt->len < fmt->cap)
fmt->buf[fmt->len] = c;
if (c == '\n')
@@ -259,74 +256,48 @@ static void fmtobj(struct fmt *fmt, fz_obj *obj)
}
int
-fz_sprintobj(char *s, fz_obj *obj)
+fz_sprintobj(char *s, int n, fz_obj *obj, int tight)
{
struct fmt fmt;
fmt.indent = 0;
- fmt.tight = 0;
fmt.col = 0;
fmt.sep = 0;
fmt.last = 0;
- fmt.file = nil;
+ fmt.tight = tight;
fmt.buf = s;
+ fmt.cap = n;
fmt.len = 0;
fmtobj(&fmt, obj);
- return fmt.len;
-}
-int
-fz_sprintcobj(char *s, fz_obj *obj)
-{
- struct fmt fmt;
-
- fmt.indent = 0;
- fmt.tight = 1;
- fmt.col = 0;
- fmt.sep = 0;
- fmt.last = 0;
+ if (fmt.buf && fmt.len < fmt.cap)
+ fmt.buf[fmt.len] = '\0';
- fmt.file = nil;
- fmt.buf = s;
- fmt.len = 0;
- fmtobj(&fmt, obj);
return fmt.len;
}
-int
-fz_fprintobj(FILE *file, fz_obj *obj)
+void
+fz_debugobj(fz_obj *obj)
{
- struct fmt fmt;
+ char buf[1024];
+ char *ptr;
+ int n;
- fmt.indent = 0;
- fmt.tight = 0;
- fmt.col = 0;
- fmt.sep = 0;
- fmt.last = 0;
-
- fmt.file = file;
- fmt.buf = nil;
- fmt.len = 0;
- fmtobj(&fmt, obj);
- return fmt.len;
-}
-
-int
-fz_fprintcobj(FILE *file, fz_obj *obj)
-{
- struct fmt fmt;
-
- fmt.indent = 0;
- fmt.tight = 1;
- fmt.col = 0;
- fmt.sep = 0;
- fmt.last = 0;
-
- fmt.file = file;
- fmt.buf = nil;
- fmt.len = 0;
- fmtobj(&fmt, obj);
- return fmt.len;
+ n = fz_sprintobj(nil, 0, obj, 0);
+ if (n < sizeof buf)
+ {
+ fz_sprintobj(buf, sizeof buf, obj, 0);
+ fwrite(buf, 1, n, stdout);
+ }
+ else
+ {
+ ptr = fz_malloc(n);
+ if (!ptr)
+ return;
+ fz_sprintobj(ptr, n, obj, 0);
+ fwrite(ptr, 1, n, stdout);
+ fz_free(ptr);
+ }
}
diff --git a/test/mupdf.c b/test/pdfdebug.c
index b51eb43d..d63a720c 100644
--- a/test/mupdf.c
+++ b/test/pdfdebug.c
@@ -112,7 +112,7 @@ void printobject(pdf_xref *xref, int oid, int gid)
if (error) fz_abort(error);
printf("%d %d obj\n", oid, gid);
- fz_fprintobj(stdout, obj);
+ fz_debugobj(obj);
printf("\n");
if (stmofs != -1) {
printf("stream\n");
@@ -153,7 +153,7 @@ void showpage(pdf_xref *xref, fz_obj *page)
fz_obj *contents;
int i;
- fz_fprintobj(stdout, page);
+ fz_debugobj(page);
printf("\n");
resources = fz_dictgets(page, "Resources");
@@ -173,9 +173,9 @@ void showpage(pdf_xref *xref, fz_obj *page)
printf("resources:\n");
printf(" font:\n");
-fz_fprintobj(stdout, rdb->font);
+fz_debugobj(rdb->font);
printf("\n extgstate:\n");
-fz_fprintobj(stdout, rdb->extgstate);
+fz_debugobj(rdb->extgstate);
printf("\nfitz tree:\n");
error = pdf_newcsi(&csi);
@@ -319,7 +319,7 @@ int main(int argc, char **argv)
if (optind == argc)
{
printf("trailer\n");
- fz_fprintobj(stdout, xref->trailer);
+ fz_debugobj(xref->trailer);
printf("\n");
}
@@ -330,6 +330,8 @@ int main(int argc, char **argv)
}
}
+printf("done.\n");
+
pdf_closexref(xref);
return 0;
diff --git a/tree/debug.c b/tree/debug.c
index f5012c60..2e7cfc4f 100644
--- a/tree/debug.c
+++ b/tree/debug.c
@@ -13,7 +13,7 @@ static void lispmeta(fz_meta *node, int level)
fz_node *child;
indent(level);
printf("(meta ");
- fz_fprintcobj(stdout, node->info);
+ fz_debugobj(node->info);
printf("\n");
for (child = node->child; child; child = child->next)
lispnode(child, level + 1);