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,7 +744,6 @@ class QPDF
744 class ObjCache; 744 class ObjCache;
745 class EncryptionParameters; 745 class EncryptionParameters;
746 class ForeignStreamData; 746 class ForeignStreamData;
747 - class CopiedStreamDataProvider;  
748 class StringDecrypter; 747 class StringDecrypter;
749 class ResolveRecorder; 748 class ResolveRecorder;
750 class JSONReactor; 749 class JSONReactor;
libqpdf/QPDF.cc
@@ -28,6 +28,8 @@ using namespace qpdf; @@ -28,6 +28,8 @@ using namespace qpdf;
28 using namespace std::literals; 28 using namespace std::literals;
29 29
30 using Objects = QPDF::Doc::Objects; 30 using Objects = QPDF::Doc::Objects;
  31 +using Foreign = Objects::Foreign;
  32 +using Streams = Objects::Streams;
31 33
32 // This must be a fixed value. This API returns a const reference to it, and the C API relies on its 34 // This must be a fixed value. This API returns a const reference to it, and the C API relies on its
33 // being static as well. 35 // being static as well.
@@ -122,24 +124,24 @@ QPDF::ForeignStreamData::ForeignStreamData( @@ -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 QPDFObjectHandle::StreamDataProvider(true), 128 QPDFObjectHandle::StreamDataProvider(true),
127 - destination_qpdf(destination_qpdf) 129 + qpdf(qpdf)
128 { 130 {
129 } 131 }
130 132
131 bool 133 bool
132 -QPDF::CopiedStreamDataProvider::provideStreamData( 134 +Streams::Copier::provideStreamData(
133 QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) 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 bool result = false; 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 foreign_data->second, pipeline, suppress_warnings, will_retry); 141 foreign_data->second, pipeline, suppress_warnings, will_retry);
140 QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1); 142 QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1);
141 } else { 143 } else {
142 - auto foreign_stream = foreign_streams[og]; 144 + auto foreign_stream = copied_streams[og];
143 result = foreign_stream.pipeStreamData( 145 result = foreign_stream.pipeStreamData(
144 pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry); 146 pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
145 QTC::TC("qpdf", "QPDF copy foreign with foreign_stream", result ? 0 : 1); 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,9 +671,6 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign_oh)
669 671
670 Dictionary dict = result.getDict(); 672 Dictionary dict = result.getDict();
671 Dictionary old_dict = foreign_oh.getDict(); 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 QPDFObjGen local_og(result.getObjGen()); 674 QPDFObjGen local_og(result.getObjGen());
676 // Copy information from the foreign stream so we can pipe its data later without keeping the 675 // Copy information from the foreign stream so we can pipe its data later without keeping the
677 // original QPDF object around. 676 // original QPDF object around.
@@ -697,14 +696,14 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign_oh) @@ -697,14 +696,14 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign_oh)
697 result.replaceStreamData(stream_buffer, dict["/Filter"], dict["/DecodeParms"]); 696 result.replaceStreamData(stream_buffer, dict["/Filter"], dict["/DecodeParms"]);
698 } else if (stream_provider) { 697 } else if (stream_provider) {
699 // In this case, the remote stream's QPDF must stay in scope. 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 result.replaceStreamData( 700 result.replaceStreamData(
702 - m->copied_stream_data_provider, dict["/Filter"], dict["/DecodeParms"]); 701 + m->objects.streams().copier(), dict["/Filter"], dict["/DecodeParms"]);
703 } else { 702 } else {
704 auto foreign_stream_data = ForeignStreamData(foreign, foreign_oh.offset(), dict); 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 result.replaceStreamData( 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,31 +106,6 @@ class QPDF::ForeignStreamData
106 bool is_root_metadata{false}; 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 class QPDF::StringDecrypter final: public QPDFObjectHandle::StringDecrypter 109 class QPDF::StringDecrypter final: public QPDFObjectHandle::StringDecrypter
135 { 110 {
136 friend class QPDF; 111 friend class QPDF;
@@ -620,6 +595,57 @@ class QPDF::Doc @@ -620,6 +595,57 @@ class QPDF::Doc
620 595
621 class Streams 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 public: 649 public:
624 static bool 650 static bool
625 pipeStreamData( 651 pipeStreamData(
@@ -649,6 +675,20 @@ class QPDF::Doc @@ -649,6 +675,20 @@ class QPDF::Doc
649 { 675 {
650 qpdf->copyStreamData(dest, src); 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 public: 694 public:
@@ -662,7 +702,8 @@ class QPDF::Doc @@ -662,7 +702,8 @@ class QPDF::Doc
662 Objects(QPDF& qpdf, QPDF::Members* m) : 702 Objects(QPDF& qpdf, QPDF::Members* m) :
663 qpdf(qpdf), 703 qpdf(qpdf),
664 m(m), 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,6 +713,12 @@ class QPDF::Doc
672 return foreign_; 713 return foreign_;
673 } 714 }
674 715
  716 + Streams&
  717 + streams()
  718 + {
  719 + return streams_;
  720 + }
  721 +
675 void parse(char const* password); 722 void parse(char const* password);
676 std::shared_ptr<QPDFObject> const& resolve(QPDFObjGen og); 723 std::shared_ptr<QPDFObject> const& resolve(QPDFObjGen og);
677 void inParse(bool); 724 void inParse(bool);
@@ -748,6 +795,7 @@ class QPDF::Doc @@ -748,6 +795,7 @@ class QPDF::Doc
748 QPDF::Members* m; 795 QPDF::Members* m;
749 796
750 Foreign foreign_; 797 Foreign foreign_;
  798 + Streams streams_;
751 }; // class QPDF::Doc::Objects 799 }; // class QPDF::Doc::Objects
752 800
753 // This class is used to represent a PDF Pages tree. 801 // This class is used to represent a PDF Pages tree.
@@ -929,7 +977,6 @@ class QPDF::Members @@ -929,7 +977,6 @@ class QPDF::Members
929 bool ever_pushed_inherited_attributes_to_pages{false}; 977 bool ever_pushed_inherited_attributes_to_pages{false};
930 bool ever_called_get_all_pages{false}; 978 bool ever_called_get_all_pages{false};
931 std::vector<QPDFExc> warnings; 979 std::vector<QPDFExc> warnings;
932 - std::shared_ptr<CopiedStreamDataProvider> copied_stream_data_provider;  
933 bool reconstructed_xref{false}; 980 bool reconstructed_xref{false};
934 bool in_read_xref_stream{false}; 981 bool in_read_xref_stream{false};
935 bool fixed_dangling_refs{false}; 982 bool fixed_dangling_refs{false};