diff options
Diffstat (limited to 'libqpdf')
-rw-r--r-- | libqpdf/QPDFJob.cc | 35 | ||||
-rw-r--r-- | libqpdf/QPDFJob_config.cc | 31 | ||||
-rw-r--r-- | libqpdf/qpdf/auto_job_help.hh | 8 |
3 files changed, 52 insertions, 22 deletions
diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index b2f905a1..a7cb3e3a 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -1,10 +1,6 @@ #include <qpdf/QPDFJob.hh> -#include <cctype> -#include <cstdio> -#include <cstdlib> #include <cstring> -#include <fcntl.h> #include <iostream> #include <memory> @@ -14,13 +10,11 @@ #include <qpdf/Pl_DCT.hh> #include <qpdf/Pl_Discard.hh> #include <qpdf/Pl_Flate.hh> -#include <qpdf/Pl_OStream.hh> #include <qpdf/Pl_StdioFile.hh> #include <qpdf/Pl_String.hh> #include <qpdf/QIntC.hh> #include <qpdf/QPDF.hh> #include <qpdf/QPDFAcroFormDocumentHelper.hh> -#include <qpdf/QPDFArgParser.hh> #include <qpdf/QPDFCryptoProvider.hh> #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh> #include <qpdf/QPDFExc.hh> @@ -2419,26 +2413,32 @@ QPDFJob::handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_hea dh.removePage(page); } - if (m->collate && (parsed_specs.size() > 1)) { + auto n_collate = m->collate.size(); + auto n_specs = parsed_specs.size(); + if (n_collate > 0 && n_specs > 1) { // Collate the pages by selecting one page from each spec in order. When a spec runs out of // pages, stop selecting from it. std::vector<QPDFPageData> new_parsed_specs; - size_t nspecs = parsed_specs.size(); - size_t cur_page = 0; + // Make sure we have a collate value for each spec. We have already checked that a non-empty + // collate has either one value or one value per spec. + for (auto i = n_collate; i < n_specs; ++i) { + m->collate.push_back(m->collate.at(0)); + } + std::vector<size_t> cur_page(n_specs, 0); bool got_pages = true; while (got_pages) { got_pages = false; - for (size_t i = 0; i < nspecs; ++i) { + for (size_t i = 0; i < n_specs; ++i) { QPDFPageData& page_data = parsed_specs.at(i); - for (size_t j = 0; j < m->collate; ++j) { - if (cur_page + j < page_data.selected_pages.size()) { + for (size_t j = 0; j < m->collate.at(i); ++j) { + if (cur_page.at(i) + j < page_data.selected_pages.size()) { got_pages = true; new_parsed_specs.emplace_back( - page_data, page_data.selected_pages.at(cur_page + j)); + page_data, page_data.selected_pages.at(cur_page.at(i) + j)); } } + cur_page.at(i) += m->collate.at(i); } - cur_page += m->collate; } parsed_specs = new_parsed_specs; } @@ -3019,9 +3019,10 @@ QPDFJob::writeOutfile(QPDF& pdf) try { QUtil::remove_file(backup.c_str()); } catch (QPDFSystemError& e) { - *m->log->getError() << m->message_prefix << ": unable to delete original file (" - << e.what() << ");" << " original file left in " << backup - << ", but the input was successfully replaced\n"; + *m->log->getError() + << m->message_prefix << ": unable to delete original file (" << e.what() << ");" + << " original file left in " << backup + << ", but the input was successfully replaced\n"; } } } diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index 4798ce9b..a0dc10f6 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -98,8 +98,27 @@ QPDFJob::Config::collate() QPDFJob::Config* QPDFJob::Config::collate(std::string const& parameter) { - auto n = (parameter.empty() ? 1 : QUtil::string_to_uint(parameter.c_str())); - o.m->collate = QIntC::to_size(n); + if (parameter.empty()) { + o.m->collate.push_back(1); + return this; + } + size_t pos = 0; + // Parse a,b,c + while (true) { + auto end = parameter.find(',', pos); + auto n = parameter.substr(pos, end); + if (n.empty()) { + usage("--collate: trailing comma"); + } + o.m->collate.push_back(QIntC::to_size(QUtil::string_to_uint(n.c_str()))); + if (end == std::string::npos) { + break; + } + pos = end + 1; + } + if (o.m->collate.empty()) { + o.m->collate.push_back(1); + } return this; } @@ -932,9 +951,15 @@ QPDFJob::Config::pages() QPDFJob::Config* QPDFJob::PagesConfig::endPages() { - if (this->config->o.m->page_specs.empty()) { + auto n_specs = config->o.m->page_specs.size(); + if (n_specs == 0) { usage("--pages: no page specifications given"); } + auto n_collate = config->o.m->collate.size(); + if (!(n_collate == 0 || n_collate == 1 || n_collate == n_specs)) { + usage("--pages: if --collate has more than one value, it must have one value per page " + "specification"); + } return this->config; } diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh index 4ee0f56e..c83f94b4 100644 --- a/libqpdf/qpdf/auto_job_help.hh +++ b/libqpdf/qpdf/auto_job_help.hh @@ -315,11 +315,13 @@ ap.addOptionHelp("--pages", "modification", "begin page selection", R"(--pages f Run qpdf --help=page-selection for details. )"); -ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate[=n] +ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate[=n[,m,...]] Collate rather than concatenate pages specified with --pages. With a numeric parameter, collate in groups of n. The default -is 1. Run qpdf --help=page-selection for additional details. +is 1. With comma-separated numeric parameters, take n from the +first file, m from the second, etc. Run +qpdf --help=page-selection for additional details. )"); ap.addOptionHelp("--split-pages", "modification", "write pages to separate files", R"(--split-pages[=n] @@ -607,6 +609,8 @@ Run qpdf --help=page-ranges for help with page ranges. Use --collate=n to cause pages to be collated in groups of n pages (default 1) instead of concatenating the input. +Use --collate=i,j,k,... to take i from the first, then j from the +second, then k from the third, then i from the first, etc. Examples: |