Commit 01dbae428d7c856a1a63625e15912ceddbf6eb67

Authored by m-holger
1 parent cabd582e

Refactor `replaceForeignIndirectObjects`: simplify object replacement logic, str…

…eamline type-specific handling, and remove redundant test coverage evaluations.
libqpdf/QPDF.cc
... ... @@ -609,53 +609,53 @@ QPDFObjectHandle
609 609 QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
610 610 {
611 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 615 if (mapping == obj_copier.object_map.end()) {
617 616 // This case would occur if this is a reference to a Pages object that we didn't
618 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 636 if (!value.null()) {
635 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 648 if (!value.null()) {
645 649 dict.replaceKey(key, replaceForeignIndirectObjects(value, obj_copier, false));
646 650 }
647 651 }
648 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 659 return result;
660 660 }
661 661  
... ...
qpdf/qpdf.testcov
... ... @@ -126,11 +126,6 @@ QPDF_Stream unknown stream length 0
126 126 QPDF replaceReserved 0
127 127 QPDF copyForeign direct 0
128 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 129 QPDFWriter copy use_aes 1
135 130 QPDFParser indirect without context 0
136 131 QPDFObjectHandle trailing data in parse 0
... ...