#ifndef MUPDF_FITZ_STREAM_H1#define MUPDF_FITZ_STREAM_H23#include "mupdf/fitz/system.h"4#include "mupdf/fitz/context.h"5#include "mupdf/fitz/buffer.h"67/*8fz_stream is a buffered reader capable of seeking in both9directions.1011Streams are reference counted, so references must be dropped12by a call to fz_drop_stream.1314Only the data between rp and wp is valid.15*/16typedef struct fz_stream_s fz_stream;1718/*19fz_open_file: Open the named file and wrap it in a stream.2021filename: Path to a file. On non-Windows machines the filename should22be exactly as it would be passed to open(2). On Windows machines, the23path should be UTF-8 encoded so that non-ASCII characters can be24represented. Other platforms do the encoding as standard anyway (and25in most cases, particularly for MacOS and Linux, the encoding they26use is UTF-8 anyway).27*/28fz_stream *fz_open_file(fz_context *ctx, const char *filename);2930fz_stream *fz_open_fd_progressive(fz_context *ctx, int fd, int bps);31fz_stream *fz_open_file_progressive(fz_context *ctx, const char *filename, int bps);3233/*34fz_open_file_w: Open the named file and wrap it in a stream.3536This function is only available when compiling for Win32.3738filename: Wide character path to the file as it would be given39to _wopen().40*/41fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename);4243/*44fz_open_fd: Wrap an open file descriptor in a stream.4546file: An open file descriptor supporting bidirectional47seeking. The stream will take ownership of the file48descriptor, so it may not be modified or closed after the call49to fz_open_fd. When the stream is closed it will also close50the file descriptor.51*/52fz_stream *fz_open_fd(fz_context *ctx, int file);5354/*55fz_open_memory: Open a block of memory as a stream.5657data: Pointer to start of data block. Ownership of the data block is58NOT passed in.5960len: Number of bytes in data block.6162Returns pointer to newly created stream. May throw exceptions on63failure to allocate.64*/65fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len);6667/*68fz_open_buffer: Open a buffer as a stream.6970buf: The buffer to open. Ownership of the buffer is NOT passed in71(this function takes it's own reference).7273Returns pointer to newly created stream. May throw exceptions on74failure to allocate.75*/76fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf);7778/*79fz_open_leecher: Attach a filter to a stream that will store any80characters read from the stream into the supplied buffer.8182chain: The underlying stream to leech from.8384buf: The buffer into which the read data should be appended.85The buffer will be resized as required.8687Returns pointer to newly created stream. May throw exceptions on88failure to allocate.89*/90fz_stream *fz_open_leecher(fz_context *ctx, fz_stream *chain, fz_buffer *buf);9192/*93fz_drop_stream: Close an open stream.9495Drops a reference for the stream. Once no references remain96the stream will be closed, as will any file descriptor the97stream is using.9899Does not throw exceptions.100*/101void fz_drop_stream(fz_context *ctx, fz_stream *stm);102103/*104fz_tell: return the current reading position within a stream105*/106int fz_tell(fz_context *ctx, fz_stream *stm);107108/*109fz_seek: Seek within a stream.110111stm: The stream to seek within.112113offset: The offset to seek to.114115whence: From where the offset is measured (see fseek).116*/117void fz_seek(fz_context *ctx, fz_stream *stm, int offset, int whence);118119/*120fz_read: Read from a stream into a given data block.121122stm: The stream to read from.123124data: The data block to read into.125126len: The length of the data block (in bytes).127128Returns the number of bytes read. May throw exceptions.129*/130int fz_read(fz_context *ctx, fz_stream *stm, unsigned char *data, int len);131132/*133fz_read_all: Read all of a stream into a buffer.134135stm: The stream to read from136137initial: Suggested initial size for the buffer.138139Returns a buffer created from reading from the stream. May throw140exceptions on failure to allocate.141*/142fz_buffer *fz_read_all(fz_context *ctx, fz_stream *stm, int initial);143144/*145fz_read_file: Read all the contents of a file into a buffer.146*/147fz_buffer *fz_read_file(fz_context *ctx, const char *filename);148149enum150{151FZ_STREAM_META_PROGRESSIVE = 1,152FZ_STREAM_META_LENGTH = 2153};154155int fz_stream_meta(fz_context *ctx, fz_stream *stm, int key, int size, void *ptr);156157typedef int (fz_stream_next_fn)(fz_context *ctx, fz_stream *stm, int max);158typedef void (fz_stream_close_fn)(fz_context *ctx, void *state);159typedef void (fz_stream_seek_fn)(fz_context *ctx, fz_stream *stm, int offset, int whence);160typedef int (fz_stream_meta_fn)(fz_context *ctx, fz_stream *stm, int key, int size, void *ptr);161162struct fz_stream_s163{164int refs;165int error;166int eof;167int pos;168int avail;169int bits;170unsigned char *rp, *wp;171void *state;172fz_stream_next_fn *next;173fz_stream_close_fn *close;174fz_stream_seek_fn *seek;175fz_stream_meta_fn *meta;176};177178fz_stream *fz_new_stream(fz_context *ctx, void *state, fz_stream_next_fn *next, fz_stream_close_fn *close);179180fz_stream *fz_keep_stream(fz_context *ctx, fz_stream *stm);181182/*183fz_read_best: Attempt to read a stream into a buffer. If truncated184is NULL behaves as fz_read_all, otherwise does not throw exceptions185in the case of failure, but instead sets a truncated flag.186187stm: The stream to read from.188189initial: Suggested initial size for the buffer.190191truncated: Flag to store success/failure indication in.192193Returns a buffer created from reading from the stream.194*/195fz_buffer *fz_read_best(fz_context *ctx, fz_stream *stm, int initial, int *truncated);196197void fz_read_line(fz_context *ctx, fz_stream *stm, char *buf, int max);198199/*200fz_available: Ask how many bytes are available immediately from201a given stream.202203stm: The stream to read from.204205max: A hint for the underlying stream; the maximum number of206bytes that we are sure we will want to read. If you do not know207this number, give 1.208209Returns the number of bytes immediately available between the210read and write pointers. This number is guaranteed only to be 0211if we have hit EOF. The number of bytes returned here need have212no relation to max (could be larger, could be smaller).213*/214static inline size_t fz_available(fz_context *ctx, fz_stream *stm, int max)215{216size_t len = stm->wp - stm->rp;217int c = EOF;218219if (len)220return len;221fz_try(ctx)222{223c = stm->next(ctx, stm, max);224}225fz_catch(ctx)226{227fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);228fz_warn(ctx, "read error; treating as end of file");229stm->error = 1;230c = EOF;231}232if (c == EOF)233{234stm->eof = 1;235return 0;236}237stm->rp--;238return stm->wp - stm->rp;239}240241static inline int fz_read_byte(fz_context *ctx, fz_stream *stm)242{243int c = EOF;244245if (stm->rp != stm->wp)246return *stm->rp++;247fz_try(ctx)248{249c = stm->next(ctx, stm, 1);250}251fz_catch(ctx)252{253fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);254fz_warn(ctx, "read error; treating as end of file");255stm->error = 1;256c = EOF;257}258if (c == EOF)259stm->eof = 1;260return c;261}262263static inline int fz_peek_byte(fz_context *ctx, fz_stream *stm)264{265int c;266267if (stm->rp != stm->wp)268return *stm->rp;269270c = stm->next(ctx, stm, 1);271if (c != EOF)272stm->rp--;273return c;274}275276static inline void fz_unread_byte(fz_context *ctx, fz_stream *stm)277{278stm->rp--;279}280281static inline int fz_is_eof(fz_context *ctx, fz_stream *stm)282{283if (stm->rp == stm->wp)284{285if (stm->eof)286return 1;287return fz_peek_byte(ctx, stm) == EOF;288}289return 0;290}291292static inline unsigned int fz_read_bits(fz_context *ctx, fz_stream *stm, int n)293{294unsigned int x;295296if (n <= stm->avail)297{298stm->avail -= n;299x = (stm->bits >> stm->avail) & ((1 << n) - 1);300}301else302{303x = stm->bits & ((1 << stm->avail) - 1);304n -= stm->avail;305stm->avail = 0;306307while (n > 8)308{309x = (x << 8) | fz_read_byte(ctx, stm);310n -= 8;311}312313if (n > 0)314{315stm->bits = fz_read_byte(ctx, stm);316stm->avail = 8 - n;317x = (x << n) | (stm->bits >> stm->avail);318}319}320321return x;322}323324static inline void fz_sync_bits(fz_context *ctx, fz_stream *stm)325{326stm->avail = 0;327}328329static inline int fz_is_eof_bits(fz_context *ctx, fz_stream *stm)330{331return fz_is_eof(ctx, stm) && (stm->avail == 0 || stm->bits == EOF);332}333334#endif335336337