Commit d90b400687b46b9e90083c3e22e9393b58e232d0
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.
Showing
4 changed files
with
78 additions
and
37 deletions
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& in, QPDF* a_qpdf) | @@ -2347,10 +2347,25 @@ QPDFJob::Input::initialize(Inputs& 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& pdf) | @@ -2528,7 +2577,7 @@ QPDFJob::handlePageSpecs(QPDF& 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& pdf) | @@ -2538,7 +2587,7 @@ QPDFJob::handlePageSpecs(QPDF& 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; |