Commit 60afe4142e4399b12f21aced476df7ef719008b9
1 parent
15269f36
Refactor: separate copyStreamData from replaceForeignIndirectObjects
Showing
2 changed files
with
87 additions
and
77 deletions
include/qpdf/QPDF.hh
| @@ -1005,6 +1005,8 @@ class QPDF | @@ -1005,6 +1005,8 @@ class QPDF | ||
| 1005 | bool top); | 1005 | bool top); |
| 1006 | QPDFObjectHandle replaceForeignIndirectObjects( | 1006 | QPDFObjectHandle replaceForeignIndirectObjects( |
| 1007 | QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top); | 1007 | QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top); |
| 1008 | + void copyStreamData( | ||
| 1009 | + QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream); | ||
| 1008 | 1010 | ||
| 1009 | // Linearization Hint table structures. | 1011 | // Linearization Hint table structures. |
| 1010 | // Naming conventions: | 1012 | // Naming conventions: |
libqpdf/QPDF.cc
| @@ -2569,88 +2569,14 @@ QPDF::replaceForeignIndirectObjects( | @@ -2569,88 +2569,14 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2569 | QPDFObjectHandle old_dict = foreign.getDict(); | 2569 | QPDFObjectHandle old_dict = foreign.getDict(); |
| 2570 | std::set<std::string> keys = old_dict.getKeys(); | 2570 | std::set<std::string> keys = old_dict.getKeys(); |
| 2571 | for (std::set<std::string>::iterator iter = keys.begin(); | 2571 | for (std::set<std::string>::iterator iter = keys.begin(); |
| 2572 | - iter != keys.end(); ++iter) | ||
| 2573 | - { | 2572 | + iter != keys.end(); ++iter) |
| 2573 | + { | ||
| 2574 | dict.replaceKey( | 2574 | dict.replaceKey( |
| 2575 | *iter, | 2575 | *iter, |
| 2576 | replaceForeignIndirectObjects( | 2576 | replaceForeignIndirectObjects( |
| 2577 | old_dict.getKey(*iter), obj_copier, false)); | 2577 | old_dict.getKey(*iter), obj_copier, false)); |
| 2578 | - } | ||
| 2579 | - if (this->m->copied_stream_data_provider == 0) | ||
| 2580 | - { | ||
| 2581 | - this->m->copied_stream_data_provider = | ||
| 2582 | - new CopiedStreamDataProvider(*this); | ||
| 2583 | - this->m->copied_streams = this->m->copied_stream_data_provider; | ||
| 2584 | - } | ||
| 2585 | - QPDFObjGen local_og(result.getObjGen()); | ||
| 2586 | - // Copy information from the foreign stream so we can pipe its | ||
| 2587 | - // data later without keeping the original QPDF object around. | ||
| 2588 | - QPDF* foreign_stream_qpdf = foreign.getOwningQPDF(); | ||
| 2589 | - if (! foreign_stream_qpdf) | ||
| 2590 | - { | ||
| 2591 | - throw std::logic_error("unable to retrieve owning qpdf" | ||
| 2592 | - " from foreign stream"); | ||
| 2593 | - } | ||
| 2594 | - QPDF_Stream* stream = | ||
| 2595 | - dynamic_cast<QPDF_Stream*>( | ||
| 2596 | - QPDFObjectHandle::ObjAccessor::getObject( | ||
| 2597 | - foreign).getPointer()); | ||
| 2598 | - if (! stream) | ||
| 2599 | - { | ||
| 2600 | - throw std::logic_error("unable to retrieve underlying" | ||
| 2601 | - " stream object from foreign stream"); | ||
| 2602 | - } | ||
| 2603 | - PointerHolder<Buffer> stream_buffer = | ||
| 2604 | - stream->getStreamDataBuffer(); | ||
| 2605 | - if ((foreign_stream_qpdf->m->immediate_copy_from) && | ||
| 2606 | - (stream_buffer.getPointer() == 0)) | ||
| 2607 | - { | ||
| 2608 | - // Pull the stream data into a buffer before attempting | ||
| 2609 | - // the copy operation. Do it on the source stream so that | ||
| 2610 | - // if the source stream is copied multiple times, we don't | ||
| 2611 | - // have to keep duplicating the memory. | ||
| 2612 | - QTC::TC("qpdf", "QPDF immediate copy stream data"); | ||
| 2613 | - foreign.replaceStreamData(foreign.getRawStreamData(), | ||
| 2614 | - old_dict.getKey("/Filter"), | ||
| 2615 | - old_dict.getKey("/DecodeParms")); | ||
| 2616 | - stream_buffer = stream->getStreamDataBuffer(); | ||
| 2617 | - } | ||
| 2618 | - PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider = | ||
| 2619 | - stream->getStreamDataProvider(); | ||
| 2620 | - if (stream_buffer.getPointer()) | ||
| 2621 | - { | ||
| 2622 | - QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); | ||
| 2623 | - result.replaceStreamData(stream_buffer, | ||
| 2624 | - dict.getKey("/Filter"), | ||
| 2625 | - dict.getKey("/DecodeParms")); | ||
| 2626 | - } | ||
| 2627 | - else if (stream_provider.getPointer()) | ||
| 2628 | - { | ||
| 2629 | - // In this case, the remote stream's QPDF must stay in scope. | ||
| 2630 | - QTC::TC("qpdf", "QPDF copy foreign stream with provider"); | ||
| 2631 | - this->m->copied_stream_data_provider->registerForeignStream( | ||
| 2632 | - local_og, foreign); | ||
| 2633 | - result.replaceStreamData(this->m->copied_streams, | ||
| 2634 | - dict.getKey("/Filter"), | ||
| 2635 | - dict.getKey("/DecodeParms")); | ||
| 2636 | - } | ||
| 2637 | - else | ||
| 2638 | - { | ||
| 2639 | - PointerHolder<ForeignStreamData> foreign_stream_data = | ||
| 2640 | - new ForeignStreamData( | ||
| 2641 | - foreign_stream_qpdf->m->encp, | ||
| 2642 | - foreign_stream_qpdf->m->file, | ||
| 2643 | - foreign.getObjectID(), | ||
| 2644 | - foreign.getGeneration(), | ||
| 2645 | - stream->getOffset(), | ||
| 2646 | - stream->getLength(), | ||
| 2647 | - dict); | ||
| 2648 | - this->m->copied_stream_data_provider->registerForeignStream( | ||
| 2649 | - local_og, foreign_stream_data); | ||
| 2650 | - result.replaceStreamData(this->m->copied_streams, | ||
| 2651 | - dict.getKey("/Filter"), | ||
| 2652 | - dict.getKey("/DecodeParms")); | ||
| 2653 | } | 2578 | } |
| 2579 | + copyStreamData(result, foreign); | ||
| 2654 | } | 2580 | } |
| 2655 | else | 2581 | else |
| 2656 | { | 2582 | { |
| @@ -2668,6 +2594,88 @@ QPDF::replaceForeignIndirectObjects( | @@ -2668,6 +2594,88 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2668 | } | 2594 | } |
| 2669 | 2595 | ||
| 2670 | void | 2596 | void |
| 2597 | +QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) | ||
| 2598 | +{ | ||
| 2599 | + QPDFObjectHandle dict = result.getDict(); | ||
| 2600 | + QPDFObjectHandle old_dict = foreign.getDict(); | ||
| 2601 | + if (this->m->copied_stream_data_provider == 0) | ||
| 2602 | + { | ||
| 2603 | + this->m->copied_stream_data_provider = | ||
| 2604 | + new CopiedStreamDataProvider(*this); | ||
| 2605 | + this->m->copied_streams = this->m->copied_stream_data_provider; | ||
| 2606 | + } | ||
| 2607 | + QPDFObjGen local_og(result.getObjGen()); | ||
| 2608 | + // Copy information from the foreign stream so we can pipe its | ||
| 2609 | + // data later without keeping the original QPDF object around. | ||
| 2610 | + QPDF* foreign_stream_qpdf = foreign.getOwningQPDF(); | ||
| 2611 | + if (! foreign_stream_qpdf) | ||
| 2612 | + { | ||
| 2613 | + throw std::logic_error("unable to retrieve owning qpdf" | ||
| 2614 | + " from foreign stream"); | ||
| 2615 | + } | ||
| 2616 | + QPDF_Stream* stream = | ||
| 2617 | + dynamic_cast<QPDF_Stream*>( | ||
| 2618 | + QPDFObjectHandle::ObjAccessor::getObject( | ||
| 2619 | + foreign).getPointer()); | ||
| 2620 | + if (! stream) | ||
| 2621 | + { | ||
| 2622 | + throw std::logic_error("unable to retrieve underlying" | ||
| 2623 | + " stream object from foreign stream"); | ||
| 2624 | + } | ||
| 2625 | + PointerHolder<Buffer> stream_buffer = | ||
| 2626 | + stream->getStreamDataBuffer(); | ||
| 2627 | + if ((foreign_stream_qpdf->m->immediate_copy_from) && | ||
| 2628 | + (stream_buffer.getPointer() == 0)) | ||
| 2629 | + { | ||
| 2630 | + // Pull the stream data into a buffer before attempting | ||
| 2631 | + // the copy operation. Do it on the source stream so that | ||
| 2632 | + // if the source stream is copied multiple times, we don't | ||
| 2633 | + // have to keep duplicating the memory. | ||
| 2634 | + QTC::TC("qpdf", "QPDF immediate copy stream data"); | ||
| 2635 | + foreign.replaceStreamData(foreign.getRawStreamData(), | ||
| 2636 | + old_dict.getKey("/Filter"), | ||
| 2637 | + old_dict.getKey("/DecodeParms")); | ||
| 2638 | + stream_buffer = stream->getStreamDataBuffer(); | ||
| 2639 | + } | ||
| 2640 | + PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider = | ||
| 2641 | + stream->getStreamDataProvider(); | ||
| 2642 | + if (stream_buffer.getPointer()) | ||
| 2643 | + { | ||
| 2644 | + QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); | ||
| 2645 | + result.replaceStreamData(stream_buffer, | ||
| 2646 | + dict.getKey("/Filter"), | ||
| 2647 | + dict.getKey("/DecodeParms")); | ||
| 2648 | + } | ||
| 2649 | + else if (stream_provider.getPointer()) | ||
| 2650 | + { | ||
| 2651 | + // In this case, the remote stream's QPDF must stay in scope. | ||
| 2652 | + QTC::TC("qpdf", "QPDF copy foreign stream with provider"); | ||
| 2653 | + this->m->copied_stream_data_provider->registerForeignStream( | ||
| 2654 | + local_og, foreign); | ||
| 2655 | + result.replaceStreamData(this->m->copied_streams, | ||
| 2656 | + dict.getKey("/Filter"), | ||
| 2657 | + dict.getKey("/DecodeParms")); | ||
| 2658 | + } | ||
| 2659 | + else | ||
| 2660 | + { | ||
| 2661 | + PointerHolder<ForeignStreamData> foreign_stream_data = | ||
| 2662 | + new ForeignStreamData( | ||
| 2663 | + foreign_stream_qpdf->m->encp, | ||
| 2664 | + foreign_stream_qpdf->m->file, | ||
| 2665 | + foreign.getObjectID(), | ||
| 2666 | + foreign.getGeneration(), | ||
| 2667 | + stream->getOffset(), | ||
| 2668 | + stream->getLength(), | ||
| 2669 | + dict); | ||
| 2670 | + this->m->copied_stream_data_provider->registerForeignStream( | ||
| 2671 | + local_og, foreign_stream_data); | ||
| 2672 | + result.replaceStreamData(this->m->copied_streams, | ||
| 2673 | + dict.getKey("/Filter"), | ||
| 2674 | + dict.getKey("/DecodeParms")); | ||
| 2675 | + } | ||
| 2676 | +} | ||
| 2677 | + | ||
| 2678 | +void | ||
| 2671 | QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) | 2679 | QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) |
| 2672 | { | 2680 | { |
| 2673 | swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen()); | 2681 | swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen()); |