Commit 19073b4602b60367dfeefde3c551c374f052d400
1 parent
171027b1
Refactor stream copying: move `copyStreamData` logic into `Stream::copy_data_to`…
… and streamline stream handling.
Showing
5 changed files
with
49 additions
and
56 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -800,9 +800,6 @@ class QPDF |
| 800 | 800 | bool is_root_metadata, |
| 801 | 801 | std::unique_ptr<Pipeline>& heap); |
| 802 | 802 | |
| 803 | - // Methods to support object copying | |
| 804 | - void copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream); | |
| 805 | - | |
| 806 | 803 | struct HPageOffsetEntry; |
| 807 | 804 | struct HPageOffset; |
| 808 | 805 | struct HSharedObjectEntry; | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -112,14 +112,14 @@ namespace |
| 112 | 112 | }; |
| 113 | 113 | } // namespace |
| 114 | 114 | |
| 115 | -Streams::Copier::Data::Data(Stream& foreign, qpdf_offset_t offset, QPDFObjectHandle local_dict) : | |
| 116 | - encp(foreign.qpdf()->m->encp), | |
| 117 | - file(foreign.qpdf()->m->file), | |
| 118 | - foreign_og(foreign.id_gen()), | |
| 119 | - offset(offset), | |
| 120 | - length(foreign.getLength()), | |
| 121 | - local_dict(local_dict), | |
| 122 | - is_root_metadata(foreign.isRootMetadata()) | |
| 115 | +Streams::Copier::Data::Data(Stream& source, QPDFObjectHandle const& dest_dict) : | |
| 116 | + encp(source.qpdf()->m->encp), | |
| 117 | + file(source.qpdf()->m->file), | |
| 118 | + source_og(source.id_gen()), | |
| 119 | + offset(source.offset()), | |
| 120 | + length(source.getLength()), | |
| 121 | + dest_dict(dest_dict), | |
| 122 | + is_root_metadata(source.isRootMetadata()) | |
| 123 | 123 | { |
| 124 | 124 | } |
| 125 | 125 | |
| ... | ... | @@ -141,10 +141,10 @@ Streams::Copier::provideStreamData( |
| 141 | 141 | fd.encp, |
| 142 | 142 | fd.file, |
| 143 | 143 | streams.qpdf(), |
| 144 | - fd.foreign_og, | |
| 144 | + fd.source_og, | |
| 145 | 145 | fd.offset, |
| 146 | 146 | fd.length, |
| 147 | - fd.local_dict, | |
| 147 | + fd.dest_dict, | |
| 148 | 148 | fd.is_root_metadata, |
| 149 | 149 | pipeline, |
| 150 | 150 | suppress_warnings, |
| ... | ... | @@ -667,7 +667,7 @@ Objects::Foreign::Copier::replace_indirect_object(QPDFObjectHandle const& foreig |
| 667 | 667 | dict.replaceKey(key, replace_indirect_object(value)); |
| 668 | 668 | } |
| 669 | 669 | } |
| 670 | - qpdf.copyStreamData(result, foreign); | |
| 670 | + stream.copy_data_to(result); | |
| 671 | 671 | return result; |
| 672 | 672 | } |
| 673 | 673 | ... | ... |
libqpdf/QPDF_Stream.cc
| ... | ... | @@ -27,6 +27,12 @@ using namespace qpdf; |
| 27 | 27 | |
| 28 | 28 | using Streams = QPDF::Doc::Objects::Streams; |
| 29 | 29 | |
| 30 | +bool | |
| 31 | +Streams::immediate_copy_from() const | |
| 32 | +{ | |
| 33 | + return qpdf_.m->immediate_copy_from; | |
| 34 | +} | |
| 35 | + | |
| 30 | 36 | namespace |
| 31 | 37 | { |
| 32 | 38 | class SF_Crypt final: public QPDFStreamFilter |
| ... | ... | @@ -188,50 +194,42 @@ Stream::Stream( |
| 188 | 194 | } |
| 189 | 195 | |
| 190 | 196 | Stream |
| 191 | -Stream::copy() const | |
| 197 | +Stream::copy() | |
| 192 | 198 | { |
| 193 | 199 | Stream result = qpdf()->newStream(); |
| 194 | 200 | result.stream()->stream_dict = getDict().copy(); |
| 195 | - Streams::copyStreamData(qpdf(), result, *this); | |
| 201 | + copy_data_to(result); | |
| 196 | 202 | return result; |
| 197 | 203 | } |
| 198 | 204 | |
| 199 | 205 | void |
| 200 | -QPDF::copyStreamData(QPDFObjectHandle dest, QPDFObjectHandle source_oh) | |
| 206 | +Stream::copy_data_to(Stream& dest) | |
| 201 | 207 | { |
| 202 | - Dictionary dict = dest.getDict(); | |
| 203 | - Dictionary old_dict = source_oh.getDict(); | |
| 204 | - QPDFObjGen local_og(dest.getObjGen()); | |
| 205 | - // Copy information from the foreign stream so we can pipe its data later without keeping the | |
| 206 | - // original QPDF object around. | |
| 208 | + qpdf_expect(dest); | |
| 209 | + auto s = stream(); | |
| 210 | + auto& streams = qpdf()->doc().objects().streams(); | |
| 211 | + auto& d_streams = dest.qpdf()->doc().objects().streams(); | |
| 207 | 212 | |
| 208 | - QPDF& source_qpdf = source_oh.getQPDF("unable to retrieve owning qpdf from foreign stream"); | |
| 213 | + auto dict = dest.getDict(); | |
| 209 | 214 | |
| 210 | - Stream source = source_oh; | |
| 211 | - if (!source) { | |
| 212 | - throw std::logic_error("unable to retrieve underlying stream object from foreign stream"); | |
| 213 | - } | |
| 214 | - std::shared_ptr<Buffer> stream_buffer = source.getStreamDataBuffer(); | |
| 215 | - if (source_qpdf.m->immediate_copy_from && !stream_buffer) { | |
| 215 | + // Copy information from the foreign stream so we can pipe its data later without keeping the | |
| 216 | + // original QPDF object around. | |
| 217 | + if (streams.immediate_copy_from() && !s->stream_data) { | |
| 216 | 218 | // Pull the stream data into a buffer before attempting the copy operation. Do it on the |
| 217 | 219 | // source stream so that if the source stream is copied multiple times, we don't have to |
| 218 | 220 | // keep duplicating the memory. |
| 219 | - source.replaceStreamData( | |
| 220 | - source.getRawStreamData(), old_dict["/Filter"], old_dict["/DecodeParms"]); | |
| 221 | - stream_buffer = source.getStreamDataBuffer(); | |
| 222 | - } | |
| 223 | - auto stream_provider = source.getStreamDataProvider(); | |
| 224 | - if (stream_buffer) { | |
| 225 | - dest.replaceStreamData(stream_buffer, dict["/Filter"], dict["/DecodeParms"]); | |
| 226 | - } else if (stream_provider) { | |
| 227 | - // In this case, the remote stream's QPDF must stay in scope. | |
| 228 | - m->objects.streams().copier()->register_copy(local_og, source_oh); | |
| 229 | - dest.replaceStreamData( | |
| 230 | - m->objects.streams().copier(), dict["/Filter"], dict["/DecodeParms"]); | |
| 221 | + replaceStreamData( | |
| 222 | + getRawStreamData(), s->stream_dict["/Filter"], s->stream_dict["/DecodeParms"]); | |
| 223 | + } | |
| 224 | + if (s->stream_data) { | |
| 225 | + dest.replaceStreamData(s->stream_data, dict["/Filter"], dict["/DecodeParms"]); | |
| 226 | + } else if (s->stream_provider) { | |
| 227 | + // In this case, the source stream's QPDF must stay in scope. | |
| 228 | + d_streams.copier()->register_copy(dest, *this); | |
| 229 | + dest.replaceStreamData(d_streams.copier(), dict["/Filter"], dict["/DecodeParms"]); | |
| 231 | 230 | } else { |
| 232 | - m->objects.streams().copier()->register_copy(local_og, source, source.offset(), dict); | |
| 233 | - dest.replaceStreamData( | |
| 234 | - m->objects.streams().copier(), dict["/Filter"], dict["/DecodeParms"]); | |
| 231 | + d_streams.copier()->register_copy(dest, *this, offset(), dict); | |
| 232 | + dest.replaceStreamData(d_streams.copier(), dict["/Filter"], dict["/DecodeParms"]); | |
| 235 | 233 | } |
| 236 | 234 | } |
| 237 | 235 | ... | ... |
libqpdf/qpdf/QPDFObjectHandle_private.hh
libqpdf/qpdf/QPDF_private.hh
| ... | ... | @@ -587,15 +587,15 @@ class QPDF::Doc |
| 587 | 587 | friend class Streams; |
| 588 | 588 | |
| 589 | 589 | public: |
| 590 | - Data(Stream& foreign, qpdf_offset_t offset, QPDFObjectHandle local_dict); | |
| 590 | + Data(Stream& source, QPDFObjectHandle const& dest_dict); | |
| 591 | 591 | |
| 592 | 592 | private: |
| 593 | 593 | std::shared_ptr<EncryptionParameters> encp; |
| 594 | 594 | std::shared_ptr<InputSource> file; |
| 595 | - QPDFObjGen foreign_og; | |
| 595 | + QPDFObjGen source_og; | |
| 596 | 596 | qpdf_offset_t offset; |
| 597 | 597 | size_t length; |
| 598 | - QPDFObjectHandle local_dict; | |
| 598 | + QPDFObjectHandle dest_dict; | |
| 599 | 599 | bool is_root_metadata{false}; |
| 600 | 600 | }; |
| 601 | 601 | |
| ... | ... | @@ -628,7 +628,7 @@ class QPDF::Doc |
| 628 | 628 | qpdf_offset_t offset, |
| 629 | 629 | QPDFObjectHandle const& local_dict) |
| 630 | 630 | { |
| 631 | - copied_data.insert_or_assign(local_og, Data(foreign, offset, local_dict)); | |
| 631 | + copied_data.insert_or_assign(local_og, Data(foreign, local_dict)); | |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | 634 | private: |
| ... | ... | @@ -675,12 +675,6 @@ class QPDF::Doc |
| 675 | 675 | will_retry); |
| 676 | 676 | } |
| 677 | 677 | |
| 678 | - static void | |
| 679 | - copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src) | |
| 680 | - { | |
| 681 | - qpdf->copyStreamData(dest, src); | |
| 682 | - } | |
| 683 | - | |
| 684 | 678 | QPDF& |
| 685 | 679 | qpdf() const |
| 686 | 680 | { |
| ... | ... | @@ -693,11 +687,13 @@ class QPDF::Doc |
| 693 | 687 | return copier_; |
| 694 | 688 | } |
| 695 | 689 | |
| 690 | + bool immediate_copy_from() const; | |
| 691 | + | |
| 696 | 692 | private: |
| 697 | 693 | QPDF& qpdf_; |
| 698 | 694 | |
| 699 | 695 | std::shared_ptr<Copier> copier_; |
| 700 | - }; | |
| 696 | + }; // class QPDF::Doc::Objects::Streams | |
| 701 | 697 | |
| 702 | 698 | public: |
| 703 | 699 | Objects() = delete; | ... | ... |