Commit 01dbae428d7c856a1a63625e15912ceddbf6eb67
1 parent
cabd582e
Refactor `replaceForeignIndirectObjects`: simplify object replacement logic, str…
…eamline type-specific handling, and remove redundant test coverage evaluations.
Showing
2 changed files
with
31 additions
and
36 deletions
libqpdf/QPDF.cc
| @@ -609,53 +609,53 @@ QPDFObjectHandle | @@ -609,53 +609,53 @@ QPDFObjectHandle | ||
| 609 | QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top) | 609 | QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top) |
| 610 | { | 610 | { |
| 611 | auto foreign_tc = foreign.getTypeCode(); | 611 | auto foreign_tc = foreign.getTypeCode(); |
| 612 | - QPDFObjectHandle result; | ||
| 613 | - if ((!top) && foreign.isIndirect()) { | ||
| 614 | - QTC::TC("qpdf", "QPDF replace indirect"); | ||
| 615 | - auto mapping = obj_copier.object_map.find(foreign.getObjGen()); | 612 | + |
| 613 | + if (!top && foreign.indirect()) { | ||
| 614 | + auto mapping = obj_copier.object_map.find(foreign.id_gen()); | ||
| 616 | if (mapping == obj_copier.object_map.end()) { | 615 | if (mapping == obj_copier.object_map.end()) { |
| 617 | // This case would occur if this is a reference to a Pages object that we didn't | 616 | // This case would occur if this is a reference to a Pages object that we didn't |
| 618 | // traverse into. | 617 | // traverse into. |
| 619 | - QTC::TC("qpdf", "QPDF replace foreign indirect with null"); | ||
| 620 | - result = QPDFObjectHandle::newNull(); | ||
| 621 | - } else { | ||
| 622 | - result = mapping->second; | 618 | + return QPDFObjectHandle::newNull(); |
| 623 | } | 619 | } |
| 624 | - } else if (foreign_tc == ::ot_array) { | ||
| 625 | - QTC::TC("qpdf", "QPDF replace array"); | ||
| 626 | - result = QPDFObjectHandle::newArray(); | ||
| 627 | - for (auto const& item: foreign.as_array()) { | ||
| 628 | - result.appendItem(replaceForeignIndirectObjects(item, obj_copier, false)); | 620 | + return mapping->second; |
| 621 | + } | ||
| 622 | + | ||
| 623 | + if (foreign_tc == ::ot_array) { | ||
| 624 | + Array array = foreign; | ||
| 625 | + std::vector<QPDFObjectHandle> result; | ||
| 626 | + result.reserve(array.size()); | ||
| 627 | + for (auto const& item: array) { | ||
| 628 | + result.emplace_back(replaceForeignIndirectObjects(item, obj_copier, false)); | ||
| 629 | } | 629 | } |
| 630 | - } else if (foreign_tc == ::ot_dictionary) { | ||
| 631 | - QTC::TC("qpdf", "QPDF replace dictionary"); | ||
| 632 | - result = QPDFObjectHandle::newDictionary(); | ||
| 633 | - for (auto const& [key, value]: foreign.as_dictionary()) { | 630 | + return Array(std::move(result)); |
| 631 | + } | ||
| 632 | + | ||
| 633 | + if (foreign_tc == ::ot_dictionary) { | ||
| 634 | + auto result = Dictionary::empty(); | ||
| 635 | + for (auto const& [key, value]: Dictionary(foreign)) { | ||
| 634 | if (!value.null()) { | 636 | if (!value.null()) { |
| 635 | result.replaceKey(key, replaceForeignIndirectObjects(value, obj_copier, false)); | 637 | result.replaceKey(key, replaceForeignIndirectObjects(value, obj_copier, false)); |
| 636 | } | 638 | } |
| 637 | } | 639 | } |
| 638 | - } else if (foreign_tc == ::ot_stream) { | ||
| 639 | - QTC::TC("qpdf", "QPDF replace stream"); | ||
| 640 | - result = obj_copier.object_map[foreign.getObjGen()]; | ||
| 641 | - QPDFObjectHandle dict = result.getDict(); | ||
| 642 | - QPDFObjectHandle old_dict = foreign.getDict(); | ||
| 643 | - for (auto const& [key, value]: old_dict.as_dictionary()) { | 640 | + return result; |
| 641 | + } | ||
| 642 | + | ||
| 643 | + if (foreign_tc == ::ot_stream) { | ||
| 644 | + Stream stream = foreign; | ||
| 645 | + Stream result = obj_copier.object_map[foreign]; | ||
| 646 | + auto dict = result.getDict(); | ||
| 647 | + for (auto const& [key, value]: stream.getDict()) { | ||
| 644 | if (!value.null()) { | 648 | if (!value.null()) { |
| 645 | dict.replaceKey(key, replaceForeignIndirectObjects(value, obj_copier, false)); | 649 | dict.replaceKey(key, replaceForeignIndirectObjects(value, obj_copier, false)); |
| 646 | } | 650 | } |
| 647 | } | 651 | } |
| 648 | copyStreamData(result, foreign); | 652 | copyStreamData(result, foreign); |
| 649 | - } else { | ||
| 650 | - foreign.assertScalar(); | ||
| 651 | - result = foreign; | ||
| 652 | - result.makeDirect(); | ||
| 653 | - } | ||
| 654 | - | ||
| 655 | - if (top && (!result.isStream()) && result.isIndirect()) { | ||
| 656 | - throw std::logic_error("replacement for foreign object is indirect"); | 653 | + return result; |
| 657 | } | 654 | } |
| 658 | 655 | ||
| 656 | + foreign.assertScalar(); | ||
| 657 | + auto result = foreign; | ||
| 658 | + result.makeDirect(); | ||
| 659 | return result; | 659 | return result; |
| 660 | } | 660 | } |
| 661 | 661 |
qpdf/qpdf.testcov
| @@ -126,11 +126,6 @@ QPDF_Stream unknown stream length 0 | @@ -126,11 +126,6 @@ QPDF_Stream unknown stream length 0 | ||
| 126 | QPDF replaceReserved 0 | 126 | QPDF replaceReserved 0 |
| 127 | QPDF copyForeign direct 0 | 127 | QPDF copyForeign direct 0 |
| 128 | QPDF copyForeign not foreign 0 | 128 | QPDF copyForeign not foreign 0 |
| 129 | -QPDF replace indirect 0 | ||
| 130 | -QPDF replace array 0 | ||
| 131 | -QPDF replace dictionary 0 | ||
| 132 | -QPDF replace stream 0 | ||
| 133 | -QPDF replace foreign indirect with null 0 | ||
| 134 | QPDFWriter copy use_aes 1 | 129 | QPDFWriter copy use_aes 1 |
| 135 | QPDFParser indirect without context 0 | 130 | QPDFParser indirect without context 0 |
| 136 | QPDFObjectHandle trailing data in parse 0 | 131 | QPDFObjectHandle trailing data in parse 0 |