Commit eadfa25bd449e01460a7746ffb167e8fc57d2bde

Authored by m-holger
1 parent e10932f3

Refactor `CopiedStreamDataProvider`: move functionality to `Streams::Copier`, im…

…prove encapsulation, and streamline stream data handling.
include/qpdf/QPDF.hh
... ... @@ -744,7 +744,6 @@ class QPDF
744 744 class ObjCache;
745 745 class EncryptionParameters;
746 746 class ForeignStreamData;
747   - class CopiedStreamDataProvider;
748 747 class StringDecrypter;
749 748 class ResolveRecorder;
750 749 class JSONReactor;
... ...
libqpdf/QPDF.cc
... ... @@ -28,6 +28,8 @@ using namespace qpdf;
28 28 using namespace std::literals;
29 29  
30 30 using Objects = QPDF::Doc::Objects;
  31 +using Foreign = Objects::Foreign;
  32 +using Streams = Objects::Streams;
31 33  
32 34 // This must be a fixed value. This API returns a const reference to it, and the C API relies on its
33 35 // being static as well.
... ... @@ -122,24 +124,24 @@ QPDF::ForeignStreamData::ForeignStreamData(
122 124 {
123 125 }
124 126  
125   -QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(QPDF& destination_qpdf) :
  127 +Streams::Copier::Copier(QPDF& qpdf) :
126 128 QPDFObjectHandle::StreamDataProvider(true),
127   - destination_qpdf(destination_qpdf)
  129 + qpdf(qpdf)
128 130 {
129 131 }
130 132  
131 133 bool
132   -QPDF::CopiedStreamDataProvider::provideStreamData(
  134 +Streams::Copier::provideStreamData(
133 135 QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry)
134 136 {
135   - auto foreign_data = foreign_stream_data.find(og);
  137 + auto foreign_data = copied_data.find(og);
136 138 bool result = false;
137   - if (foreign_data != foreign_stream_data.end()) {
138   - result = destination_qpdf.pipeForeignStreamData(
  139 + if (foreign_data != copied_data.end()) {
  140 + result = qpdf.pipeForeignStreamData(
139 141 foreign_data->second, pipeline, suppress_warnings, will_retry);
140 142 QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1);
141 143 } else {
142   - auto foreign_stream = foreign_streams[og];
  144 + auto foreign_stream = copied_streams[og];
143 145 result = foreign_stream.pipeStreamData(
144 146 pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
145 147 QTC::TC("qpdf", "QPDF copy foreign with foreign_stream", result ? 0 : 1);
... ... @@ -669,9 +671,6 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign_oh)
669 671  
670 672 Dictionary dict = result.getDict();
671 673 Dictionary old_dict = foreign_oh.getDict();
672   - if (!m->copied_stream_data_provider) {
673   - m->copied_stream_data_provider = std::make_shared<CopiedStreamDataProvider>(*this);
674   - }
675 674 QPDFObjGen local_og(result.getObjGen());
676 675 // Copy information from the foreign stream so we can pipe its data later without keeping the
677 676 // original QPDF object around.
... ... @@ -697,14 +696,14 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign_oh)
697 696 result.replaceStreamData(stream_buffer, dict["/Filter"], dict["/DecodeParms"]);
698 697 } else if (stream_provider) {
699 698 // In this case, the remote stream's QPDF must stay in scope.
700   - m->copied_stream_data_provider->registerForeignStream(local_og, foreign_oh);
  699 + m->objects.streams().copier()->register_copy(local_og, foreign_oh);
701 700 result.replaceStreamData(
702   - m->copied_stream_data_provider, dict["/Filter"], dict["/DecodeParms"]);
  701 + m->objects.streams().copier(), dict["/Filter"], dict["/DecodeParms"]);
703 702 } else {
704 703 auto foreign_stream_data = ForeignStreamData(foreign, foreign_oh.offset(), dict);
705   - m->copied_stream_data_provider->registerForeignStream(local_og, foreign_stream_data);
  704 + m->objects.streams().copier()->register_copy(local_og, foreign_stream_data);
706 705 result.replaceStreamData(
707   - m->copied_stream_data_provider, dict["/Filter"], dict["/DecodeParms"]);
  706 + m->objects.streams().copier(), dict["/Filter"], dict["/DecodeParms"]);
708 707 }
709 708 }
710 709  
... ...
libqpdf/qpdf/QPDF_private.hh
... ... @@ -106,31 +106,6 @@ class QPDF::ForeignStreamData
106 106 bool is_root_metadata{false};
107 107 };
108 108  
109   -class QPDF::CopiedStreamDataProvider final: public QPDFObjectHandle::StreamDataProvider
110   -{
111   - public:
112   - CopiedStreamDataProvider(QPDF& destination_qpdf);
113   - ~CopiedStreamDataProvider() final = default;
114   - bool provideStreamData(
115   - QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) final;
116   - void
117   - registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream)
118   - {
119   - foreign_streams.insert_or_assign(local_og, foreign_stream);
120   - }
121   -
122   - void
123   - registerForeignStream(QPDFObjGen local_og, ForeignStreamData foreign_stream)
124   - {
125   - foreign_stream_data.insert_or_assign(local_og, foreign_stream);
126   - }
127   -
128   - private:
129   - QPDF& destination_qpdf;
130   - std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
131   - std::map<QPDFObjGen, ForeignStreamData> foreign_stream_data;
132   -};
133   -
134 109 class QPDF::StringDecrypter final: public QPDFObjectHandle::StringDecrypter
135 110 {
136 111 friend class QPDF;
... ... @@ -620,6 +595,57 @@ class QPDF::Doc
620 595  
621 596 class Streams
622 597 {
  598 + // Copier manages the copying of streams into this PDF. It is used both for copying
  599 + // local and foreign streams.
  600 + class Copier final: public QPDFObjectHandle::StreamDataProvider
  601 + {
  602 + public:
  603 + Copier() = delete;
  604 + Copier(StreamDataProvider const&) = delete;
  605 + Copier(StreamDataProvider&&) = delete;
  606 + Copier& operator=(StreamDataProvider const&) = delete;
  607 + Copier& operator=(StreamDataProvider&&) = delete;
  608 +
  609 + Copier(QPDF& qpdf);
  610 + ~Copier() final = default;
  611 +
  612 + bool provideStreamData(
  613 + QPDFObjGen const& og,
  614 + Pipeline* pipeline,
  615 + bool suppress_warnings,
  616 + bool will_retry) final;
  617 +
  618 + void
  619 + register_copy(QPDFObjGen local_og, QPDFObjectHandle foreign_stream)
  620 + {
  621 + copied_streams.insert_or_assign(local_og, foreign_stream);
  622 + }
  623 +
  624 + void
  625 + register_copy(QPDFObjGen local_og, ForeignStreamData foreign_stream)
  626 + {
  627 + copied_data.insert_or_assign(local_og, foreign_stream);
  628 + }
  629 +
  630 + private:
  631 + QPDF& qpdf;
  632 + std::map<QPDFObjGen, QPDFObjectHandle> copied_streams;
  633 + std::map<QPDFObjGen, ForeignStreamData> copied_data;
  634 + };
  635 +
  636 + public:
  637 + Streams(QPDF& qpdf) :
  638 + qpdf(qpdf)
  639 + {
  640 + }
  641 +
  642 + Streams() = delete;
  643 + Streams(Streams const&) = delete;
  644 + Streams(Streams&&) = delete;
  645 + Streams& operator=(Streams const&) = delete;
  646 + Streams& operator=(Streams&&) = delete;
  647 + ~Streams() = default;
  648 +
623 649 public:
624 650 static bool
625 651 pipeStreamData(
... ... @@ -649,6 +675,20 @@ class QPDF::Doc
649 675 {
650 676 qpdf->copyStreamData(dest, src);
651 677 }
  678 +
  679 + std::shared_ptr<Copier>&
  680 + copier()
  681 + {
  682 + if (!copier_) {
  683 + copier_ = std::make_shared<Copier>(qpdf);
  684 + }
  685 + return copier_;
  686 + }
  687 +
  688 + private:
  689 + QPDF& qpdf;
  690 +
  691 + std::shared_ptr<Copier> copier_;
652 692 };
653 693  
654 694 public:
... ... @@ -662,7 +702,8 @@ class QPDF::Doc
662 702 Objects(QPDF& qpdf, QPDF::Members* m) :
663 703 qpdf(qpdf),
664 704 m(m),
665   - foreign_(qpdf)
  705 + foreign_(qpdf),
  706 + streams_(qpdf)
666 707 {
667 708 }
668 709  
... ... @@ -672,6 +713,12 @@ class QPDF::Doc
672 713 return foreign_;
673 714 }
674 715  
  716 + Streams&
  717 + streams()
  718 + {
  719 + return streams_;
  720 + }
  721 +
675 722 void parse(char const* password);
676 723 std::shared_ptr<QPDFObject> const& resolve(QPDFObjGen og);
677 724 void inParse(bool);
... ... @@ -748,6 +795,7 @@ class QPDF::Doc
748 795 QPDF::Members* m;
749 796  
750 797 Foreign foreign_;
  798 + Streams streams_;
751 799 }; // class QPDF::Doc::Objects
752 800  
753 801 // This class is used to represent a PDF Pages tree.
... ... @@ -929,7 +977,6 @@ class QPDF::Members
929 977 bool ever_pushed_inherited_attributes_to_pages{false};
930 978 bool ever_called_get_all_pages{false};
931 979 std::vector<QPDFExc> warnings;
932   - std::shared_ptr<CopiedStreamDataProvider> copied_stream_data_provider;
933 980 bool reconstructed_xref{false};
934 981 bool in_read_xref_stream{false};
935 982 bool fixed_dangling_refs{false};
... ...