Commit d90b400687b46b9e90083c3e22e9393b58e232d0

Authored by m-holger
1 parent 2c6a3e97

Refactor `QPDFJob::Selection` and `Inputs`: replace `Selection::filename` with `…

…input_entry`, centralize input file handling in `infile_name`, update `new_selection` logic, and simplify page range and input processing.
include/qpdf/QPDFJob.hh
@@ -463,8 +463,6 @@ class QPDFJob @@ -463,8 +463,6 @@ class QPDFJob
463 void setQPDFOptions(QPDF& pdf); 463 void setQPDFOptions(QPDF& pdf);
464 void handlePageSpecs(QPDF& pdf); 464 void handlePageSpecs(QPDF& pdf);
465 bool shouldRemoveUnreferencedResources(QPDF& pdf); 465 bool shouldRemoveUnreferencedResources(QPDF& pdf);
466 - void new_selection(  
467 - std::string const& filename, std::string const& password, std::string const& range);  
468 void handleRotations(QPDF& pdf); 466 void handleRotations(QPDF& pdf);
469 void getUOPagenos( 467 void getUOPagenos(
470 std::vector<UnderOverlay>& uo, std::vector<std::map<size_t, std::vector<int>>>& pagenos); 468 std::vector<UnderOverlay>& uo, std::vector<std::map<size_t, std::vector<int>>>& pagenos);
libqpdf/QPDFJob.cc
@@ -2347,10 +2347,25 @@ QPDFJob::Input::initialize(Inputs&amp; in, QPDF* a_qpdf) @@ -2347,10 +2347,25 @@ QPDFJob::Input::initialize(Inputs&amp; in, QPDF* a_qpdf)
2347 } 2347 }
2348 2348
2349 void 2349 void
2350 -QPDFJob::Inputs::new_selection(  
2351 - std::string const& filename, std::string const& password, std::string const& range) 2350 +QPDFJob::Inputs::infile_name(std::string const& name)
2352 { 2351 {
2353 - selections.emplace_back(filename, password, range); 2352 + if (!infile_name_.empty()) {
  2353 + usage("input file has already been given");
  2354 + }
  2355 + infile_name_ = name;
  2356 +
  2357 + auto& in_entry = *files.insert({name, Input()}).first;
  2358 + auto it = files.find("");
  2359 + if (it != files.end()) {
  2360 + // We allready have selection entries for the main input file. We need to fix them to point
  2361 + // to the correct files entry.
  2362 + for (auto& selection: selections) {
  2363 + if (selection.in_entry == &*it) {
  2364 + selection.in_entry = &in_entry;
  2365 + }
  2366 + }
  2367 + files.erase(it);
  2368 + }
2354 } 2369 }
2355 2370
2356 void 2371 void
@@ -2394,6 +2409,9 @@ QPDFJob::Inputs::process_all() @@ -2394,6 +2409,9 @@ QPDFJob::Inputs::process_all()
2394 selection.process(*this); 2409 selection.process(*this);
2395 } 2410 }
2396 2411
  2412 + if (!infile_name().empty()) {
  2413 + files.erase("");
  2414 + }
2397 if (!keep_files_open_set) { 2415 if (!keep_files_open_set) {
2398 // Count the number of distinct files to determine whether we should keep files open or not. 2416 // Count the number of distinct files to determine whether we should keep files open or not.
2399 // Rather than trying to code some portable heuristic based on OS limits, just hard-code 2417 // Rather than trying to code some portable heuristic based on OS limits, just hard-code
@@ -2415,20 +2433,20 @@ QPDFJob::Inputs::process_all() @@ -2415,20 +2433,20 @@ QPDFJob::Inputs::process_all()
2415 for (auto& selection: selections) { 2433 for (auto& selection: selections) {
2416 // Read original pages from the PDF, and parse the page range associated with this 2434 // Read original pages from the PDF, and parse the page range associated with this
2417 // occurrence of the file. 2435 // occurrence of the file.
2418 - auto const& file_spec = files[selection.filename]; 2436 + auto const& input = selection.input();
2419 if (selection.range.empty()) { 2437 if (selection.range.empty()) {
2420 - selection.selected_pages.reserve(static_cast<size_t>(file_spec.n_pages));  
2421 - for (int i = 1; i <= file_spec.n_pages; ++i) { 2438 + selection.selected_pages.reserve(static_cast<size_t>(input.n_pages));
  2439 + for (int i = 1; i <= input.n_pages; ++i) {
2422 selection.selected_pages.push_back(i); 2440 selection.selected_pages.push_back(i);
2423 } 2441 }
2424 continue; 2442 continue;
2425 } 2443 }
2426 try { 2444 try {
2427 selection.selected_pages = 2445 selection.selected_pages =
2428 - QUtil::parse_numrange(selection.range.data(), files[selection.filename].n_pages); 2446 + QUtil::parse_numrange(selection.range.data(), selection.input().n_pages);
2429 } catch (std::runtime_error& e) { 2447 } catch (std::runtime_error& e) {
2430 throw std::runtime_error( 2448 throw std::runtime_error(
2431 - "parsing numeric range for " + selection.filename + ": " + e.what()); 2449 + "parsing numeric range for " + selection.filename() + ": " + e.what());
2432 } 2450 }
2433 } 2451 }
2434 } 2452 }
@@ -2446,16 +2464,47 @@ QPDFJob::Inputs::clear() @@ -2446,16 +2464,47 @@ QPDFJob::Inputs::clear()
2446 return any_warnings; 2464 return any_warnings;
2447 } 2465 }
2448 2466
  2467 +QPDFJob::Selection&
  2468 +QPDFJob::Inputs::new_selection(std::string const& filename)
  2469 +{
  2470 + // Handle "." as a shortcut for the input file. Note that infile_name may not be known yet, in
  2471 + // which case we are wrongly entering an empty name. This will be corrected in the infile_name
  2472 + // setter.
  2473 + return selections.emplace_back(
  2474 + *files.insert({(filename == "." ? infile_name() : filename), Input()}).first);
  2475 +}
  2476 +
  2477 +void
  2478 +QPDFJob::Inputs::new_selection(
  2479 + std::string const& filename, std::string const& password, std::string const& range)
  2480 +{
  2481 + auto& selection = new_selection(filename);
  2482 + selection.password = password;
  2483 + selection.range = range;
  2484 +}
  2485 +
  2486 +QPDFJob::Selection::Selection(std::pair<const std::string, QPDFJob::Input>& entry) :
  2487 + in_entry(&entry)
  2488 +{
  2489 +}
  2490 +
  2491 +QPDFJob::Input&
  2492 +QPDFJob::Selection::input()
  2493 +{
  2494 + return in_entry->second;
  2495 +}
  2496 +
  2497 +std::string const&
  2498 +QPDFJob::Selection::filename()
  2499 +{
  2500 + return in_entry->first;
  2501 +}
  2502 +
2449 void 2503 void
2450 QPDFJob::Selection::process(QPDFJob::Inputs& in) 2504 QPDFJob::Selection::process(QPDFJob::Inputs& in)
2451 { 2505 {
2452 - // Handle "." as a shortcut for the input file.  
2453 - if (filename == ".") {  
2454 - filename = in.infile_name();  
2455 - }  
2456 - auto& input = in.files[filename];  
2457 if (!password.empty()) { 2506 if (!password.empty()) {
2458 - input.password = password; 2507 + input().password = password;
2459 } 2508 }
2460 } 2509 }
2461 2510
@@ -2528,7 +2577,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf) @@ -2528,7 +2577,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf)
2528 auto& this_afdh = pdf.acroform(); 2577 auto& this_afdh = pdf.acroform();
2529 std::set<QPDFObjGen> referenced_fields; 2578 std::set<QPDFObjGen> referenced_fields;
2530 for (auto& selection: new_specs.empty() ? m->inputs.selections : new_specs) { 2579 for (auto& selection: new_specs.empty() ? m->inputs.selections : new_specs) {
2531 - auto& input = m->inputs.files[selection.filename]; 2580 + auto& input = selection.input();
2532 if (input.cfis) { 2581 if (input.cfis) {
2533 input.cfis->stayOpen(true); 2582 input.cfis->stayOpen(true);
2534 } 2583 }
@@ -2538,7 +2587,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf) @@ -2538,7 +2587,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf)
2538 any_page_labels = true; 2587 any_page_labels = true;
2539 } 2588 }
2540 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 2589 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
2541 - v << prefix << ": adding pages from " << selection.filename << "\n"; 2590 + v << prefix << ": adding pages from " << selection.filename() << "\n";
2542 }); 2591 });
2543 for (auto pageno_iter: selection.selected_pages) { 2592 for (auto pageno_iter: selection.selected_pages) {
2544 // Pages are specified from 1 but numbered from 0 in the vector 2593 // Pages are specified from 1 but numbered from 0 in the vector
libqpdf/QPDFJob_config.cc
@@ -1001,7 +1001,7 @@ QPDFJob::PagesConfig::pageSpec( @@ -1001,7 +1001,7 @@ QPDFJob::PagesConfig::pageSpec(
1001 QPDFJob::PagesConfig* 1001 QPDFJob::PagesConfig*
1002 QPDFJob::PagesConfig::file(std::string const& arg) 1002 QPDFJob::PagesConfig::file(std::string const& arg)
1003 { 1003 {
1004 - config->o.m->inputs.new_selection(arg, {}, {}); 1004 + (void)config->o.m->inputs.new_selection(arg);
1005 return this; 1005 return this;
1006 } 1006 }
1007 1007
libqpdf/qpdf/QPDFJob_private.hh
@@ -10,25 +10,24 @@ @@ -10,25 +10,24 @@
10 // single clause in the --pages option. 10 // single clause in the --pages option.
11 struct QPDFJob::Selection 11 struct QPDFJob::Selection
12 { 12 {
13 - Selection(std::string const& filename, std::string const& password, std::string const& range) :  
14 - filename(filename),  
15 - password(password),  
16 - range(range)  
17 - {  
18 - } 13 + Selection() = delete;
  14 +
  15 + Selection(std::pair<const std::string, QPDFJob::Input>& entry);
19 16
20 Selection(QPDFJob::Selection const& other, int page) : 17 Selection(QPDFJob::Selection const& other, int page) :
21 - filename(other.filename),  
22 - // range and password are no longer required when this constructor is called. 18 + in_entry(other.in_entry),
23 selected_pages({page}) 19 selected_pages({page})
24 { 20 {
25 } 21 }
26 22
  23 + QPDFJob::Input& input();
  24 + std::string const& filename();
  25 +
27 void process(Inputs& in); 26 void process(Inputs& in);
28 27
29 - std::string filename; 28 + std::pair<const std::string, QPDFJob::Input>* in_entry{nullptr};
30 std::string password; 29 std::string password;
31 - std::string range; 30 + std::string range; // An empty range means all pages.
32 std::vector<int> selected_pages; 31 std::vector<int> selected_pages;
33 }; 32 };
34 33
@@ -66,6 +65,8 @@ struct QPDFJob::Inputs @@ -66,6 +65,8 @@ struct QPDFJob::Inputs
66 // Destroy all owned QPDF objects. Return false if any of the QPDF objects recorded warnings. 65 // Destroy all owned QPDF objects. Return false if any of the QPDF objects recorded warnings.
67 bool clear(); 66 bool clear();
68 67
  68 + Selection& new_selection(std::string const& filename);
  69 +
69 void new_selection( 70 void new_selection(
70 std::string const& filename, std::string const& password, std::string const& range); 71 std::string const& filename, std::string const& password, std::string const& range);
71 72
@@ -75,14 +76,7 @@ struct QPDFJob::Inputs @@ -75,14 +76,7 @@ struct QPDFJob::Inputs
75 return infile_name_; 76 return infile_name_;
76 } 77 }
77 78
78 - void  
79 - infile_name(std::string const& name)  
80 - {  
81 - if (!infile_name_.empty()) {  
82 - usage("input file has already been given");  
83 - }  
84 - infile_name_ = name;  
85 - } 79 + void infile_name(std::string const& name);
86 80
87 std::string infile_name_; 81 std::string infile_name_;
88 std::string encryption_file; 82 std::string encryption_file;