2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-11-02 19:49:43 +00:00
qpdf/libqpdf/FileInputSource.cc
Jay Berkenbilt cb769c62e5 WHITESPACE ONLY -- expand tabs in source code
This comment expands all tabs using an 8-character tab-width. You
should ignore this commit when using git blame or use git blame -w.

In the early days, I used to use tabs where possible for indentation,
since emacs did this automatically. In recent years, I have switched
to only using spaces, which means qpdf source code has been a mixture
of spaces and tabs. I have avoided cleaning this up because of not
wanting gratuitous whitespaces change to cloud the output of git
blame, but I changed my mind after discussing with users who view qpdf
source code in editors/IDEs that have other tab widths by default and
in light of the fact that I am planning to start applying automatic
code formatting soon.
2022-02-08 11:51:15 -05:00

152 lines
3.6 KiB
C++

#include <qpdf/FileInputSource.hh>
#include <string.h>
#include <qpdf/QUtil.hh>
#include <qpdf/QPDFExc.hh>
#include <algorithm>
FileInputSource::Members::Members(bool close_file) :
close_file(close_file),
file(0)
{
}
FileInputSource::Members::~Members()
{
if (this->file && this->close_file)
{
fclose(this->file);
}
}
FileInputSource::FileInputSource() :
m(new Members(false))
{
}
void
FileInputSource::setFilename(char const* filename)
{
this->m = PointerHolder<Members>(new Members(true));
this->m->filename = filename;
this->m->file = QUtil::safe_fopen(filename, "rb");
}
void
FileInputSource::setFile(
char const* description, FILE* filep, bool close_file)
{
this->m = PointerHolder<Members>(new Members(close_file));
this->m->filename = description;
this->m->file = filep;
this->seek(0, SEEK_SET);
}
FileInputSource::~FileInputSource()
{
}
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->m->file);
size_t len = this->read(buf, sizeof(buf));
if (len == 0)
{
done = true;
result = this->tell();
}
else
{
char* p1 = static_cast<char*>(memchr(buf, '\r', len));
char* p2 = static_cast<char*>(memchr(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->m->filename;
}
qpdf_offset_t
FileInputSource::tell()
{
return QUtil::tell(this->m->file);
}
void
FileInputSource::seek(qpdf_offset_t offset, int whence)
{
QUtil::os_wrapper(std::string("seek to ") +
this->m->filename + ", offset " +
QUtil::int_to_string(offset) + " (" +
QUtil::int_to_string(whence) + ")",
QUtil::seek(this->m->file, offset, whence));
}
void
FileInputSource::rewind()
{
::rewind(this->m->file);
}
size_t
FileInputSource::read(char* buffer, size_t length)
{
this->last_offset = this->tell();
size_t len = fread(buffer, 1, length, this->m->file);
if (len == 0)
{
if (ferror(this->m->file))
{
throw QPDFExc(qpdf_e_system,
this->m->filename, "",
this->last_offset,
std::string("read ") +
QUtil::uint_to_string(length) + " bytes");
}
else if (length > 0)
{
this->seek(0, SEEK_END);
this->last_offset = this->tell();
}
}
return len;
}
void
FileInputSource::unreadCh(char ch)
{
QUtil::os_wrapper(this->m->filename + ": unread character",
ungetc(static_cast<unsigned char>(ch), this->m->file));
}