Commit 60afe4142e4399b12f21aced476df7ef719008b9

Authored by Jay Berkenbilt
1 parent 15269f36

Refactor: separate copyStreamData from replaceForeignIndirectObjects

include/qpdf/QPDF.hh
... ... @@ -1005,6 +1005,8 @@ class QPDF
1005 1005 bool top);
1006 1006 QPDFObjectHandle replaceForeignIndirectObjects(
1007 1007 QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
  1008 + void copyStreamData(
  1009 + QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
1008 1010  
1009 1011 // Linearization Hint table structures.
1010 1012 // Naming conventions:
... ...
libqpdf/QPDF.cc
... ... @@ -2569,88 +2569,14 @@ QPDF::replaceForeignIndirectObjects(
2569 2569 QPDFObjectHandle old_dict = foreign.getDict();
2570 2570 std::set<std::string> keys = old_dict.getKeys();
2571 2571 for (std::set<std::string>::iterator iter = keys.begin();
2572   - iter != keys.end(); ++iter)
2573   - {
  2572 + iter != keys.end(); ++iter)
  2573 + {
2574 2574 dict.replaceKey(
2575 2575 *iter,
2576 2576 replaceForeignIndirectObjects(
2577 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 2581 else
2656 2582 {
... ... @@ -2668,6 +2594,88 @@ QPDF::replaceForeignIndirectObjects(
2668 2594 }
2669 2595  
2670 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 2679 QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
2672 2680 {
2673 2681 swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen());
... ...