diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvi2bitmap/FileByteStream.cc |
Initial commit
Diffstat (limited to 'dviware/dvi2bitmap/FileByteStream.cc')
-rw-r--r-- | dviware/dvi2bitmap/FileByteStream.cc | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/dviware/dvi2bitmap/FileByteStream.cc b/dviware/dvi2bitmap/FileByteStream.cc new file mode 100644 index 0000000000..121de93206 --- /dev/null +++ b/dviware/dvi2bitmap/FileByteStream.cc @@ -0,0 +1,130 @@ +/* This file is part of dvi2bitmap; see README for copyrights and licence */ + +#include <config.h> + +#include <FileByteStream.h> + +#include <iostream> +//#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#ifdef HAVE_CSTD_INCLUDE +#include <cstdio> +#include <cerrno> +#include <cassert> +#include <cstring> // for strerror +#else +#include <stdio.h> +#include <errno.h> +#include <assert.h> +#include <string.h> +#endif + +using STD::cerr; +using STD::endl; + + +/** + * Opens the requested file. If preload is true, then open the file + * and read it entire into memory (possibly helpful if the client will + * be seeking a lot). If the file can't be opened, then try adding + * <code>tryext</code> to the end of it. + * + * <p>The file to be opened must be a seekable object -- that is, it + * must be a regular file, rather than a named pipe or a socket. The + * constructor checks this, and throws an exception if this is not the + * case. If you wish to open a named pipe, you can do so using {@link + * InputByteStream#InputByteStream(string)}. + * + * @param filename the file to be opened + * @param tryext a file extension, including any dot, which should be + * added to the end of <code>filename</code> if that cannot be opened; + * default <code>""</code> suppresses this + * @param preload if true, then the file is read entirely into memory + * + * @throws InputByteStreamError if there is a problem opening the + * file, including the discovery that it is not a seekable object + */ +FileByteStream::FileByteStream(string& filename, + string tryext, + bool preload) + throw (InputByteStreamError) +{ + if (getVerbosity() > normal) + cerr << "FileByteStream(name=" << filename + << ",ext=" << tryext + << ",preload=" << (preload?"yes":"no") << ")" << endl; + int newfd = -1; + try { + newfd = openSourceSpec("<osfile>" + filename); + } catch (InputByteStreamError& e) { + newfd = -1; + } + if (newfd < 0) { + newfd = openSourceSpec("<osfile>" + filename + tryext); + // Let it throw the exception, this time + // If it succeeds, modify the argument + filename += tryext; + } + assert(newfd >= 0); + + // ermm, we should test for HAVE_SYS_STAT_H, here, but (a) are + // there really any platforms which don't have stat?, and (b) we + // need the filesize information, and I don't know how else to + // get it. Deal with this if we really do find such a wierd + // platform. +#ifndef HAVE_SYS_STAT_H +#error "Come on -- you _must_ have stat(2)!" +#endif + struct stat S; + if (fstat (newfd, &S)) + { + string errstr = STD::strerror (errno); + throw InputByteStreamError ("Can't stat open file (" + errstr + ")"); + } + filesize_ = S.st_size; + + bindToFileDescriptor(newfd, + filename, + (preload ? filesize_ : 0), + preload, + true); // assert is seekable +} + +FileByteStream::~FileByteStream() +{ + // nothing +} + +/** + * Sets the position of the file pointer. + * + * @param pos if positive, the offset from the beginning of the file; + * if negative, the offset from the end of the file + * + * @throws InputByteStreamError if the offset is larger + * than the size of the file + */ +void FileByteStream::seek(int pos) + throw (InputByteStreamError) +{ + int fd = getFD(); + int offset = (pos >= 0 ? pos : filesize_ + pos); + if (offset < 0 || offset > filesize_) + throw InputByteStreamError("FileByteStream: seek out of bounds"); + + if (fd < 0) { + // preloaded + bufferSeek(offset); + // no need to reload buffer + } else { + if (lseek(fd, offset, SEEK_SET) < 0) { + string errmsg = STD::strerror(errno); + throw InputByteStreamError("Can't seek (" + errmsg + ")"); + } + if (getVerbosity() > normal) + cerr << "FileByteStream::seek(" << pos << "=>" << offset + << ") ok" << endl; + reloadBuffer(); + } +} |