diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-03-11 19:04:17 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-03-17 19:38:40 +0000 |
commit | 551de42088c58dc69fba06fb53e36c2ddb12367f (patch) | |
tree | f073b5ac7d3dee2de2f5609a13fd9c47e605d3d8 /include | |
parent | 8fdcb140930c3027841af28a4632ce6d23aa44b6 (diff) | |
download | mupdf-551de42088c58dc69fba06fb53e36c2ddb12367f.tar.xz |
Rework fz_streams.
Currently fz_streams have a 4K buffer within their header. The call
to read from a stream fills this buffer, resulting in more data being
pulled from any underlying stream than we might like. This causes
problems with the forthcoming 'leech' filter.
Here we simplify the fields available in the public stream header.
No specific buffer is given; simply the read and write pointers.
The underlying 'read' function is replaced by a 'next' function
that makes the next block of data available and returns the first
character of it (or EOF).
A caller to the 'next' function should supply the maximum number of
bytes that it knows it will need (possibly not now, but eventually).
This enables the underlying stream to efficiently decode just enough.
The underlying stream is free to return fewer, or a greater number
if it wants to.
The exact size of the 'block' of data returned will depend on the
filter in use and (possibly) the data therein.
Callers can get the currently available amount of data by calling
fz_available (but again should pass the maximum amount of data they know
they will need). The only time this will ever return 0 is if we have
hit EOF.
Diffstat (limited to 'include')
-rw-r--r-- | include/mupdf/fitz/stream.h | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/include/mupdf/fitz/stream.h b/include/mupdf/fitz/stream.h index 206ba5be..9f38ea17 100644 --- a/include/mupdf/fitz/stream.h +++ b/include/mupdf/fitz/stream.h @@ -138,7 +138,7 @@ int fz_stream_meta(fz_stream *stm, int key, int size, void *ptr); void fz_rebind_stream(fz_stream *stm, fz_context *ctx); -typedef int (fz_stream_read_fn)(fz_stream *stm, unsigned char *buf, int len); +typedef int (fz_stream_next_fn)(fz_stream *stm, int max); typedef void (fz_stream_close_fn)(fz_context *ctx, void *state); typedef void (fz_stream_seek_fn)(fz_stream *stm, int offset, int whence); typedef int (fz_stream_meta_fn)(fz_stream *stm, int key, int size, void *ptr); @@ -153,23 +153,21 @@ struct fz_stream_s int pos; int avail; int bits; - unsigned char *bp, *rp, *wp, *ep; + unsigned char *rp, *wp; void *state; - fz_stream_read_fn *read; + fz_stream_next_fn *next; fz_stream_close_fn *close; fz_stream_seek_fn *seek; fz_stream_meta_fn *meta; fz_stream_rebind_fn *rebind; - unsigned char buf[4096]; }; fz_stream *fz_new_stream(fz_context *ctx, void *state, - fz_stream_read_fn *read, + fz_stream_next_fn *next, fz_stream_close_fn *close, fz_stream_rebind_fn *rebind); fz_stream *fz_keep_stream(fz_stream *stm); -void fz_fill_buffer(fz_stream *stm); /* fz_read_best: Attempt to read a stream into a buffer. If truncated @@ -188,30 +186,86 @@ fz_buffer *fz_read_best(fz_stream *stm, int initial, int *truncated); void fz_read_line(fz_stream *stm, char *buf, int max); -static inline int fz_read_byte(fz_stream *stm) +/* + fz_available: Ask how many bytes are available immediately from + a given stream. + + stm: The stream to read from. + + max: A hint for the underlying stream; the maximum number of + bytes that we are sure we will want to read. If you do not know + this number, give 1. + + Returns the number of bytes immediately available between the + read and write pointers. This number is guaranteed only to be 0 + if we have hit EOF. The number of bytes returned here need have + no relation to max (could be larger, could be smaller). +*/ +static inline int fz_available(fz_stream *stm, int max) { - if (stm->rp == stm->wp) + int len = stm->wp - stm->rp; + int c; + + if (len) + return len; + fz_try(stm->ctx) + { + c = stm->next(stm, max); + } + fz_catch(stm->ctx) { - fz_fill_buffer(stm); - return stm->rp < stm->wp ? *stm->rp++ : EOF; + fz_rethrow_if(stm->ctx, FZ_ERROR_TRYLATER); + fz_warn(stm->ctx, "read error; treating as end of file"); + stm->error = 1; + c = EOF; } - return *stm->rp++; + if (c == EOF) + { + stm->eof = 1; + return 0; + } + stm->rp--; + return stm->wp - stm->rp; } -static inline int fz_peek_byte(fz_stream *stm) +static inline int fz_read_byte(fz_stream *stm) { - if (stm->rp == stm->wp) + int c; + + if (stm->rp != stm->wp) + return *stm->rp++; + fz_try(stm->ctx) { - fz_fill_buffer(stm); - return stm->rp < stm->wp ? *stm->rp : EOF; + c = stm->next(stm, 1); } - return *stm->rp; + fz_catch(stm->ctx) + { + fz_rethrow_if(stm->ctx, FZ_ERROR_TRYLATER); + fz_warn(stm->ctx, "read error; treating as end of file"); + stm->error = 1; + c = EOF; + } + if (c == EOF) + stm->eof = 1; + return c; } -static inline void fz_unread_byte(fz_stream *stm) +static inline int fz_peek_byte(fz_stream *stm) { - if (stm->rp > stm->bp) + int c; + + if (stm->rp != stm->wp) + return *stm->rp; + + c = stm->next(stm, 1); + if (c != EOF) stm->rp--; + return c; +} + +static inline void fz_unread_byte(fz_stream *stm) +{ + stm->rp--; } static inline int fz_is_eof(fz_stream *stm) |