From 43d9ee56ea958428ce3a8e395a029035d81f914f Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 5 Mar 2023 12:27:15 +0000 Subject: [PATCH] Split QPDFJob::run into createQPDF and writeQPDF Also, change QPDFJob to use unique_ptr instead of shared pointers. --- include/qpdf/QPDFJob.hh | 27 +++++++++++++++++------ libqpdf/QPDFJob.cc | 48 ++++++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 9bf81fcc..2a82d61c 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -397,6 +397,21 @@ class QPDFJob QPDF_DLL void run(); + // The following two methods allow a job to be run in two stages - creation + // of a QPDF object and writing of the QPDF object. This allows the QPDF + // object to be modified prior to writing it out. See + // examples/qpdfjob-remove-annotations for an illustration of its use. + + // Run the first stage of the job. Return a nullptr if the configuration is + // not valid. + QPDF_DLL + std::unique_ptr createQPDF(); + + // Run the second stage of the job. Do nothing if a nullptr is passed as + // parameter. + QPDF_DLL + void writeQPDF(QPDF& qpdf); + // CHECK STATUS -- these methods provide information known after // run() is called. @@ -474,7 +489,7 @@ class QPDFJob std::string to_nr; std::string from_nr; std::string repeat_nr; - std::shared_ptr pdf; + std::unique_ptr pdf; std::vector to_pagenos; std::vector from_pagenos; std::vector repeat_pagenos; @@ -490,25 +505,25 @@ class QPDFJob // Basic file processing void processFile( - std::shared_ptr&, + std::unique_ptr&, char const* filename, char const* password, bool used_for_input, bool main_input); void processInputSource( - std::shared_ptr&, + std::unique_ptr&, std::shared_ptr is, char const* password, bool used_for_input); void doProcess( - std::shared_ptr&, + std::unique_ptr&, std::function fn, char const* password, bool empty, bool used_for_input, bool main_input); void doProcessOnce( - std::shared_ptr&, + std::unique_ptr&, std::function fn, char const* password, bool empty, @@ -518,7 +533,7 @@ class QPDFJob // Transformations void setQPDFOptions(QPDF& pdf); void - handlePageSpecs(QPDF& pdf, std::vector>& page_heap); + handlePageSpecs(QPDF& pdf, std::vector>& page_heap); bool shouldRemoveUnreferencedResources(QPDF& pdf); void handleRotations(QPDF& pdf); void diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 87ec32b9..b57a791b 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -447,11 +447,11 @@ QPDFJob::parseNumrange(char const* range, int max) return std::vector(); } -void -QPDFJob::run() +std::unique_ptr +QPDFJob::createQPDF() { checkConfiguration(); - std::shared_ptr pdf_sp; + std::unique_ptr pdf_sp; try { processFile(pdf_sp, m->infilename.get(), m->password.get(), true, true); } catch (QPDFExc& e) { @@ -461,12 +461,12 @@ QPDFJob::run() if (m->check_is_encrypted || m->check_requires_password) { this->m->encryption_status = qpdf_es_encrypted | qpdf_es_password_incorrect; - return; + return nullptr; } if (m->show_encryption && pdf_sp) { this->m->log->info("Incorrect password supplied\n"); showEncryption(*pdf_sp); - return; + return nullptr; } } throw e; @@ -477,7 +477,7 @@ QPDFJob::run() } if (m->check_is_encrypted || m->check_requires_password) { - return; + return nullptr; } // If we are updating from JSON, this has to be done first before @@ -486,7 +486,7 @@ QPDFJob::run() pdf.updateFromJSON(this->m->update_from_json); } - std::vector> page_heap; + std::vector> page_heap; if (!m->page_specs.empty()) { handlePageSpecs(pdf, page_heap); } @@ -495,7 +495,12 @@ QPDFJob::run() } handleUnderOverlay(pdf); handleTransformations(pdf); + return pdf_sp; +} +void +QPDFJob::writeQPDF(QPDF& pdf) +{ if (!createsOutput()) { doInspection(pdf); } else if (m->split_pages) { @@ -527,6 +532,15 @@ QPDFJob::run() } } +void +QPDFJob::run() +{ + auto pdf = createQPDF(); + if (pdf) { + writeQPDF(*pdf); + } +} + bool QPDFJob::hasWarnings() const { @@ -1868,14 +1882,14 @@ QPDFJob::doInspection(QPDF& pdf) void QPDFJob::doProcessOnce( - std::shared_ptr& pdf, + std::unique_ptr& pdf, std::function fn, char const* password, bool empty, bool used_for_input, bool main_input) { - pdf = QPDF::create(); + pdf = std::make_unique(); setQPDFOptions(*pdf); if (empty) { pdf->emptyPDF(); @@ -1892,7 +1906,7 @@ QPDFJob::doProcessOnce( void QPDFJob::doProcess( - std::shared_ptr& pdf, + std::unique_ptr& pdf, std::function fn, char const* password, bool empty, @@ -1976,7 +1990,7 @@ QPDFJob::doProcess( void QPDFJob::processFile( - std::shared_ptr& pdf, + std::unique_ptr& pdf, char const* filename, char const* password, bool used_for_input, @@ -1996,7 +2010,7 @@ QPDFJob::processFile( void QPDFJob::processInputSource( - std::shared_ptr& pdf, + std::unique_ptr& pdf, std::shared_ptr is, char const* password, bool used_for_input) @@ -2278,7 +2292,7 @@ QPDFJob::copyAttachments(QPDF& pdf) v << prefix << ": copying attachments from " << to_copy.path << "\n"; }); - std::shared_ptr other; + std::unique_ptr other; processFile( other, to_copy.path.c_str(), @@ -2540,7 +2554,7 @@ added_page(QPDF& pdf, QPDFPageObjectHelper page) void QPDFJob::handlePageSpecs( - QPDF& pdf, std::vector>& page_heap) + QPDF& pdf, std::vector>& page_heap) { // Parse all page specifications and translate them into lists of // actual pages. @@ -2612,10 +2626,10 @@ QPDFJob::handlePageSpecs( new FileInputSource(page_spec.filename.c_str()); is = std::shared_ptr(fis); } - std::shared_ptr qpdf_sp; + std::unique_ptr qpdf_sp; processInputSource(qpdf_sp, is, password, true); - page_heap.push_back(qpdf_sp); page_spec_qpdfs[page_spec.filename] = qpdf_sp.get(); + page_heap.push_back(std::move(qpdf_sp)); if (cis) { cis->stayOpen(false); page_spec_cfis[page_spec.filename] = cis; @@ -3116,7 +3130,7 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w) w.setSuppressOriginalObjectIDs(true); } if (m->copy_encryption) { - std::shared_ptr encryption_pdf; + std::unique_ptr encryption_pdf; processFile( encryption_pdf, m->encryption_file.c_str(),