summaryrefslogtreecommitdiff
path: root/libqpdf/FileInputSource.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf/FileInputSource.cc')
-rw-r--r--libqpdf/FileInputSource.cc141
1 files changed, 141 insertions, 0 deletions
diff --git a/libqpdf/FileInputSource.cc b/libqpdf/FileInputSource.cc
new file mode 100644
index 0000000..b1f7b5d
--- /dev/null
+++ b/libqpdf/FileInputSource.cc
@@ -0,0 +1,141 @@
+#include <qpdf/FileInputSource.hh>
+#include <string.h>
+#include <qpdf/QUtil.hh>
+#include <qpdf/QPDFExc.hh>
+
+FileInputSource::FileInputSource() :
+ close_file(false),
+ file(0)
+{
+}
+
+void
+FileInputSource::setFilename(char const* filename)
+{
+ destroy();
+ this->filename = filename;
+ this->close_file = true;
+ this->file = QUtil::fopen_wrapper(std::string("open ") + this->filename,
+ fopen(this->filename.c_str(), "rb"));
+}
+
+void
+FileInputSource::setFile(
+ char const* description, FILE* filep, bool close_file)
+{
+ destroy();
+ this->filename = description;
+ this->close_file = close_file;
+ this->file = filep;
+ this->seek(0, SEEK_SET);
+}
+
+FileInputSource::~FileInputSource()
+{
+ destroy();
+}
+
+void
+FileInputSource::destroy()
+{
+ if (this->file && this->close_file)
+ {
+ fclose(this->file);
+ this->file = 0;
+ }
+}
+
+qpdf_offset_t
+FileInputSource::findAndSkipNextEOL()
+{
+ qpdf_offset_t result = 0;
+ bool done = false;
+ char buf[10240];
+ while (! done)
+ {
+ qpdf_offset_t cur_offset = QUtil::tell(this->file);
+ size_t len = this->read(buf, sizeof(buf));
+ if (len == 0)
+ {
+ done = true;
+ result = this->tell();
+ }
+ else
+ {
+ char* p1 = (char*)memchr((void*)buf, '\r', len);
+ char* p2 = (char*)memchr((void*)buf, '\n', len);
+ char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2;
+ if (p)
+ {
+ result = cur_offset + (p - buf);
+ // We found \r or \n. Keep reading until we get past
+ // \r and \n characters.
+ this->seek(result + 1, SEEK_SET);
+ char ch;
+ while (! done)
+ {
+ if (this->read(&ch, 1) == 0)
+ {
+ done = true;
+ }
+ else if (! ((ch == '\r') || (ch == '\n')))
+ {
+ this->unreadCh(ch);
+ done = true;
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+std::string const&
+FileInputSource::getName() const
+{
+ return this->filename;
+}
+
+qpdf_offset_t
+FileInputSource::tell()
+{
+ return QUtil::tell(this->file);
+}
+
+void
+FileInputSource::seek(qpdf_offset_t offset, int whence)
+{
+ QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " +
+ QUtil::int_to_string(offset) + " (" +
+ QUtil::int_to_string(whence) + ")",
+ QUtil::seek(this->file, offset, whence));
+}
+
+void
+FileInputSource::rewind()
+{
+ ::rewind(this->file);
+}
+
+size_t
+FileInputSource::read(char* buffer, size_t length)
+{
+ this->last_offset = QUtil::tell(this->file);
+ size_t len = fread(buffer, 1, length, this->file);
+ if ((len == 0) && ferror(this->file))
+ {
+ throw QPDFExc(qpdf_e_system,
+ this->filename, "",
+ this->last_offset,
+ std::string("read ") +
+ QUtil::int_to_string(length) + " bytes");
+ }
+ return len;
+}
+
+void
+FileInputSource::unreadCh(char ch)
+{
+ QUtil::os_wrapper(this->filename + ": unread character",
+ ungetc((unsigned char)ch, this->file));
+}