aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/QPDFJob.cc35
-rw-r--r--libqpdf/QPDFJob_config.cc31
-rw-r--r--libqpdf/qpdf/auto_job_help.hh8
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: