/* * Miscellaneous I/O functions */ #include "fitz-base.h" #include "fitz-stream.h" int fz_tell(fz_stream *stm) { if (stm->mode == FZ_SREAD) return fz_rtell(stm); return fz_wtell(stm); } int fz_seek(fz_stream *stm, int offset, int whence) { if (stm->mode == FZ_SREAD) return fz_rseek(stm, offset, whence); return fz_wseek(stm, offset, whence); } /* * Read a line terminated by LF or CR or CRLF. */ int fz_readline(fz_stream *stm, char *mem, int n) { char *s = mem; int c = EOF; while (n > 1) { c = fz_readbyte(stm); if (c == EOF) break; if (c == '\r') { c = fz_peekbyte(stm); if (c == '\n') c = fz_readbyte(stm); break; } if (c == '\n') break; *s++ = c; n--; } if (n) *s = '\0'; return s - mem; } struct fz_linkedbuf_s { int len; struct fz_linkedbuf_s * next; }; typedef struct fz_linkedbuf_s fz_linkedbuf; fz_error *fz_newlinkedbuf(fz_linkedbuf **bufp, int len, unsigned char **data) { fz_linkedbuf *buf; buf = *bufp = fz_malloc(sizeof(fz_linkedbuf) + len); if (!buf) return fz_outofmem; buf->next = nil; buf->len = len; *data = (unsigned char*)buf + sizeof(fz_linkedbuf); return nil; } fz_error *fz_growlinkedbuf(fz_linkedbuf *buf, int len, unsigned char **data) { fz_linkedbuf *newbuf; fz_error *error; error = fz_newlinkedbuf(&newbuf, len, data); if (error) return error; while (buf->next) buf = buf->next; buf->next = newbuf; return nil; } void fz_droplinkedbuf(fz_linkedbuf *buf) { fz_linkedbuf *next; while (buf) { next = buf->next; fz_free(buf); buf = next; } } int fz_linkedbuflen(fz_linkedbuf *buf) { int len = 0; while (buf) { len += buf->len; buf = buf->next; } return len; } fz_error *fz_linearizelinkedbuf(fz_linkedbuf *buf, int len, unsigned char **datap) { unsigned char *data, *bufdata; int tocopy; int buflen = fz_linkedbuflen(buf); assert(len <= buflen); data = *datap = fz_malloc(len); if (!data) return fz_outofmem; while (len > 0) { bufdata = (unsigned char*)buf + sizeof(fz_linkedbuf); tocopy = MIN(len, buf->len); memmove(data, bufdata, tocopy); buf = buf->next; data += tocopy; len -= tocopy; } return nil; } /* * Utility function to consume all the contents of an input stream into * a freshly allocated buffer; realloced and trimmed to size. */ enum { MINCHUNKSIZE = 1024 * 8 }; enum { MAXCHUNKSIZE = MINCHUNKSIZE * 10 }; int fz_readall(fz_buffer **bufp, fz_stream *stm) { fz_buffer *real; fz_error *error; fz_linkedbuf *buf; unsigned char *data; int totallen; int n; int chunksize = MINCHUNKSIZE; *bufp = nil; totallen = 0; error = fz_newlinkedbuf(&buf, chunksize, &data); if (error) return -1; while (1) { n = fz_read(stm, data, chunksize); if (n < 0) { fz_free(buf); return -1; } totallen += n; if (n != chunksize) break; if (chunksize < MAXCHUNKSIZE) chunksize = chunksize + MINCHUNKSIZE; error = fz_growlinkedbuf(buf, chunksize, &data); if (error) { fz_droplinkedbuf(buf); return -1; } } error = fz_linearizelinkedbuf(buf, totallen, &data); fz_droplinkedbuf(buf); if (error) return -1; real = *bufp = fz_malloc(sizeof(fz_buffer)); if (!real) { fz_free(data); return -1; } real->refs = 1; real->ownsdata = 1; real->bp = data; real->rp = data; real->wp = data + totallen; real->ep = data + totallen; real->eof = 1; return totallen; }