diff --git a/ChangeLog b/ChangeLog index 7eef99e4..fa519fc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2018-08-04 Jay Berkenbilt + + * Add ClosedFileInputSource::stayOpen method, enabling a + ClosedFileInputSource to stay open during manually indicated + periods of high activity, thus reducing the overhead of frequent + open/close operations. + 2018-06-23 Jay Berkenbilt * 8.1.0: release diff --git a/include/qpdf/ClosedFileInputSource.hh b/include/qpdf/ClosedFileInputSource.hh index 1e3ff82f..fbd72df9 100644 --- a/include/qpdf/ClosedFileInputSource.hh +++ b/include/qpdf/ClosedFileInputSource.hh @@ -55,6 +55,13 @@ class ClosedFileInputSource: public InputSource QPDF_DLL virtual void unreadCh(char ch); + // The file stays open between calls to stayOpen(true) and + // stayOpen(false). You can use this to surround multiple + // operations on a single ClosedFileInputSource to reduce the + // overhead of a separate open/close on each call. + QPDF_DLL + void stayOpen(bool); + private: ClosedFileInputSource(ClosedFileInputSource const&); ClosedFileInputSource& operator=(ClosedFileInputSource const&); @@ -76,6 +83,7 @@ class ClosedFileInputSource: public InputSource std::string filename; qpdf_offset_t offset; FileInputSource* fis; + bool stay_open; }; PointerHolder m; }; diff --git a/libqpdf/ClosedFileInputSource.cc b/libqpdf/ClosedFileInputSource.cc index ea79a840..63357886 100644 --- a/libqpdf/ClosedFileInputSource.cc +++ b/libqpdf/ClosedFileInputSource.cc @@ -4,7 +4,8 @@ ClosedFileInputSource::Members::Members(char const* filename) : filename(filename), offset(0), - fis(0) + fis(0), + stay_open(false) { } @@ -42,6 +43,10 @@ ClosedFileInputSource::after() { this->last_offset = this->m->fis->getLastOffset(); this->m->offset = this->m->fis->tell(); + if (this->m->stay_open) + { + return; + } delete this->m->fis; this->m->fis = 0; } @@ -82,6 +87,10 @@ void ClosedFileInputSource::rewind() { this->m->offset = 0; + if (this->m->fis) + { + this->m->fis->rewind(); + } } size_t @@ -101,3 +110,13 @@ ClosedFileInputSource::unreadCh(char ch) // Don't call after -- the file has to stay open after this // operation. } + +void +ClosedFileInputSource::stayOpen(bool val) +{ + this->m->stay_open = val; + if ((! val) && this->m->fis) + { + after(); + } +} diff --git a/libtests/closed_file_input_source.cc b/libtests/closed_file_input_source.cc index 9cf5ff04..7309ca31 100644 --- a/libtests/closed_file_input_source.cc +++ b/libtests/closed_file_input_source.cc @@ -65,6 +65,11 @@ int main() std::cout << "testing with ClosedFileInputSource\n"; ClosedFileInputSource cf("input"); do_tests(&cf); + std::cout << "testing with ClosedFileInputSource in stay open mode\n"; + ClosedFileInputSource cf2("input"); + cf2.stayOpen(true); + do_tests(&cf2); + cf2.stayOpen(false); std::cout << "testing with FileInputSource\n"; FileInputSource f; f.setFilename("input"); diff --git a/libtests/qtest/closedfile/output b/libtests/qtest/closedfile/output index 7a5554af..596d1462 100644 --- a/libtests/qtest/closedfile/output +++ b/libtests/qtest/closedfile/output @@ -1,3 +1,4 @@ testing with ClosedFileInputSource +testing with ClosedFileInputSource in stay open mode testing with FileInputSource all assertions passed