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,9 +800,6 @@ class QPDF | ||
| 800 | bool is_root_metadata, | 800 | bool is_root_metadata, |
| 801 | std::unique_ptr<Pipeline>& heap); | 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 | struct HPageOffsetEntry; | 803 | struct HPageOffsetEntry; |
| 807 | struct HPageOffset; | 804 | struct HPageOffset; |
| 808 | struct HSharedObjectEntry; | 805 | struct HSharedObjectEntry; |
libqpdf/QPDF.cc
| @@ -112,14 +112,14 @@ namespace | @@ -112,14 +112,14 @@ namespace | ||
| 112 | }; | 112 | }; |
| 113 | } // namespace | 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,10 +141,10 @@ Streams::Copier::provideStreamData( | ||
| 141 | fd.encp, | 141 | fd.encp, |
| 142 | fd.file, | 142 | fd.file, |
| 143 | streams.qpdf(), | 143 | streams.qpdf(), |
| 144 | - fd.foreign_og, | 144 | + fd.source_og, |
| 145 | fd.offset, | 145 | fd.offset, |
| 146 | fd.length, | 146 | fd.length, |
| 147 | - fd.local_dict, | 147 | + fd.dest_dict, |
| 148 | fd.is_root_metadata, | 148 | fd.is_root_metadata, |
| 149 | pipeline, | 149 | pipeline, |
| 150 | suppress_warnings, | 150 | suppress_warnings, |
| @@ -667,7 +667,7 @@ Objects::Foreign::Copier::replace_indirect_object(QPDFObjectHandle const& foreig | @@ -667,7 +667,7 @@ Objects::Foreign::Copier::replace_indirect_object(QPDFObjectHandle const& foreig | ||
| 667 | dict.replaceKey(key, replace_indirect_object(value)); | 667 | dict.replaceKey(key, replace_indirect_object(value)); |
| 668 | } | 668 | } |
| 669 | } | 669 | } |
| 670 | - qpdf.copyStreamData(result, foreign); | 670 | + stream.copy_data_to(result); |
| 671 | return result; | 671 | return result; |
| 672 | } | 672 | } |
| 673 | 673 |
libqpdf/QPDF_Stream.cc
| @@ -27,6 +27,12 @@ using namespace qpdf; | @@ -27,6 +27,12 @@ using namespace qpdf; | ||
| 27 | 27 | ||
| 28 | using Streams = QPDF::Doc::Objects::Streams; | 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 | namespace | 36 | namespace |
| 31 | { | 37 | { |
| 32 | class SF_Crypt final: public QPDFStreamFilter | 38 | class SF_Crypt final: public QPDFStreamFilter |
| @@ -188,50 +194,42 @@ Stream::Stream( | @@ -188,50 +194,42 @@ Stream::Stream( | ||
| 188 | } | 194 | } |
| 189 | 195 | ||
| 190 | Stream | 196 | Stream |
| 191 | -Stream::copy() const | 197 | +Stream::copy() |
| 192 | { | 198 | { |
| 193 | Stream result = qpdf()->newStream(); | 199 | Stream result = qpdf()->newStream(); |
| 194 | result.stream()->stream_dict = getDict().copy(); | 200 | result.stream()->stream_dict = getDict().copy(); |
| 195 | - Streams::copyStreamData(qpdf(), result, *this); | 201 | + copy_data_to(result); |
| 196 | return result; | 202 | return result; |
| 197 | } | 203 | } |
| 198 | 204 | ||
| 199 | void | 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 | // Pull the stream data into a buffer before attempting the copy operation. Do it on the | 218 | // Pull the stream data into a buffer before attempting the copy operation. Do it on the |
| 217 | // source stream so that if the source stream is copied multiple times, we don't have to | 219 | // source stream so that if the source stream is copied multiple times, we don't have to |
| 218 | // keep duplicating the memory. | 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 | } else { | 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
| @@ -469,7 +469,9 @@ namespace qpdf | @@ -469,7 +469,9 @@ namespace qpdf | ||
| 469 | qpdf_offset_t offset, | 469 | qpdf_offset_t offset, |
| 470 | size_t length); | 470 | size_t length); |
| 471 | 471 | ||
| 472 | - Stream copy() const; | 472 | + Stream copy(); |
| 473 | + | ||
| 474 | + void copy_data_to(Stream& target); | ||
| 473 | 475 | ||
| 474 | Dictionary | 476 | Dictionary |
| 475 | getDict() const | 477 | getDict() const |
libqpdf/qpdf/QPDF_private.hh
| @@ -587,15 +587,15 @@ class QPDF::Doc | @@ -587,15 +587,15 @@ class QPDF::Doc | ||
| 587 | friend class Streams; | 587 | friend class Streams; |
| 588 | 588 | ||
| 589 | public: | 589 | public: |
| 590 | - Data(Stream& foreign, qpdf_offset_t offset, QPDFObjectHandle local_dict); | 590 | + Data(Stream& source, QPDFObjectHandle const& dest_dict); |
| 591 | 591 | ||
| 592 | private: | 592 | private: |
| 593 | std::shared_ptr<EncryptionParameters> encp; | 593 | std::shared_ptr<EncryptionParameters> encp; |
| 594 | std::shared_ptr<InputSource> file; | 594 | std::shared_ptr<InputSource> file; |
| 595 | - QPDFObjGen foreign_og; | 595 | + QPDFObjGen source_og; |
| 596 | qpdf_offset_t offset; | 596 | qpdf_offset_t offset; |
| 597 | size_t length; | 597 | size_t length; |
| 598 | - QPDFObjectHandle local_dict; | 598 | + QPDFObjectHandle dest_dict; |
| 599 | bool is_root_metadata{false}; | 599 | bool is_root_metadata{false}; |
| 600 | }; | 600 | }; |
| 601 | 601 | ||
| @@ -628,7 +628,7 @@ class QPDF::Doc | @@ -628,7 +628,7 @@ class QPDF::Doc | ||
| 628 | qpdf_offset_t offset, | 628 | qpdf_offset_t offset, |
| 629 | QPDFObjectHandle const& local_dict) | 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 | private: | 634 | private: |
| @@ -675,12 +675,6 @@ class QPDF::Doc | @@ -675,12 +675,6 @@ class QPDF::Doc | ||
| 675 | will_retry); | 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 | QPDF& | 678 | QPDF& |
| 685 | qpdf() const | 679 | qpdf() const |
| 686 | { | 680 | { |
| @@ -693,11 +687,13 @@ class QPDF::Doc | @@ -693,11 +687,13 @@ class QPDF::Doc | ||
| 693 | return copier_; | 687 | return copier_; |
| 694 | } | 688 | } |
| 695 | 689 | ||
| 690 | + bool immediate_copy_from() const; | ||
| 691 | + | ||
| 696 | private: | 692 | private: |
| 697 | QPDF& qpdf_; | 693 | QPDF& qpdf_; |
| 698 | 694 | ||
| 699 | std::shared_ptr<Copier> copier_; | 695 | std::shared_ptr<Copier> copier_; |
| 700 | - }; | 696 | + }; // class QPDF::Doc::Objects::Streams |
| 701 | 697 | ||
| 702 | public: | 698 | public: |
| 703 | Objects() = delete; | 699 | Objects() = delete; |