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 | 463 | void setQPDFOptions(QPDF& pdf); |
| 464 | 464 | void handlePageSpecs(QPDF& pdf); |
| 465 | 465 | bool shouldRemoveUnreferencedResources(QPDF& pdf); |
| 466 | - void new_selection( | |
| 467 | - std::string const& filename, std::string const& password, std::string const& range); | |
| 468 | 466 | void handleRotations(QPDF& pdf); |
| 469 | 467 | void getUOPagenos( |
| 470 | 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 | 2347 | } |
| 2348 | 2348 | |
| 2349 | 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 | 2371 | void |
| ... | ... | @@ -2394,6 +2409,9 @@ QPDFJob::Inputs::process_all() |
| 2394 | 2409 | selection.process(*this); |
| 2395 | 2410 | } |
| 2396 | 2411 | |
| 2412 | + if (!infile_name().empty()) { | |
| 2413 | + files.erase(""); | |
| 2414 | + } | |
| 2397 | 2415 | if (!keep_files_open_set) { |
| 2398 | 2416 | // Count the number of distinct files to determine whether we should keep files open or not. |
| 2399 | 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 | 2433 | for (auto& selection: selections) { |
| 2416 | 2434 | // Read original pages from the PDF, and parse the page range associated with this |
| 2417 | 2435 | // occurrence of the file. |
| 2418 | - auto const& file_spec = files[selection.filename]; | |
| 2436 | + auto const& input = selection.input(); | |
| 2419 | 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 | 2440 | selection.selected_pages.push_back(i); |
| 2423 | 2441 | } |
| 2424 | 2442 | continue; |
| 2425 | 2443 | } |
| 2426 | 2444 | try { |
| 2427 | 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 | 2447 | } catch (std::runtime_error& e) { |
| 2430 | 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 | 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 | 2503 | void |
| 2450 | 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 | 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 | 2577 | auto& this_afdh = pdf.acroform(); |
| 2529 | 2578 | std::set<QPDFObjGen> referenced_fields; |
| 2530 | 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 | 2581 | if (input.cfis) { |
| 2533 | 2582 | input.cfis->stayOpen(true); |
| 2534 | 2583 | } |
| ... | ... | @@ -2538,7 +2587,7 @@ QPDFJob::handlePageSpecs(QPDF& pdf) |
| 2538 | 2587 | any_page_labels = true; |
| 2539 | 2588 | } |
| 2540 | 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 | 2592 | for (auto pageno_iter: selection.selected_pages) { |
| 2544 | 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 | 1001 | QPDFJob::PagesConfig* |
| 1002 | 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 | 1005 | return this; |
| 1006 | 1006 | } |
| 1007 | 1007 | ... | ... |
libqpdf/qpdf/QPDFJob_private.hh
| ... | ... | @@ -10,25 +10,24 @@ |
| 10 | 10 | // single clause in the --pages option. |
| 11 | 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 | 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 | 19 | selected_pages({page}) |
| 24 | 20 | { |
| 25 | 21 | } |
| 26 | 22 | |
| 23 | + QPDFJob::Input& input(); | |
| 24 | + std::string const& filename(); | |
| 25 | + | |
| 27 | 26 | void process(Inputs& in); |
| 28 | 27 | |
| 29 | - std::string filename; | |
| 28 | + std::pair<const std::string, QPDFJob::Input>* in_entry{nullptr}; | |
| 30 | 29 | std::string password; |
| 31 | - std::string range; | |
| 30 | + std::string range; // An empty range means all pages. | |
| 32 | 31 | std::vector<int> selected_pages; |
| 33 | 32 | }; |
| 34 | 33 | |
| ... | ... | @@ -66,6 +65,8 @@ struct QPDFJob::Inputs |
| 66 | 65 | // Destroy all owned QPDF objects. Return false if any of the QPDF objects recorded warnings. |
| 67 | 66 | bool clear(); |
| 68 | 67 | |
| 68 | + Selection& new_selection(std::string const& filename); | |
| 69 | + | |
| 69 | 70 | void new_selection( |
| 70 | 71 | std::string const& filename, std::string const& password, std::string const& range); |
| 71 | 72 | |
| ... | ... | @@ -75,14 +76,7 @@ struct QPDFJob::Inputs |
| 75 | 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 | 81 | std::string infile_name_; |
| 88 | 82 | std::string encryption_file; | ... | ... |