diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh index ba08b88..5628a36 100644 --- a/include/qpdf/QPDFWriter.hh +++ b/include/qpdf/QPDFWriter.hh @@ -597,12 +597,14 @@ class QPDFWriter // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack // is popped. Pipeline* pushPipeline(Pipeline*); - void activatePipelineStack(PipelinePopper& pp, bool discard = false); + void + activatePipelineStack(PipelinePopper& pp, bool discard = false, std::string* str = nullptr); void initializePipelineStack(Pipeline*); void adjustAESStreamLength(size_t& length); void pushEncryptionFilter(PipelinePopper&); void pushDiscardFilter(PipelinePopper&); + void pushStringPipeline(PipelinePopper&, std::string& str); void pushMD5Pipeline(PipelinePopper&); void computeDeterministicIDData(); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 5939cab..43e1ef4 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -917,10 +917,11 @@ QPDFWriter::initializePipelineStack(Pipeline* p) } void -QPDFWriter::activatePipelineStack(PipelinePopper& pp, bool discard) +QPDFWriter::activatePipelineStack(PipelinePopper& pp, bool discard, std::string* str) { std::string stack_id("stack " + std::to_string(m->next_stack_id)); - auto* c = new pl::Count(stack_id.c_str(), discard ? nullptr : m->pipeline_stack.back()); + auto* c = str ? new pl::Count(stack_id.c_str(), str) + : new pl::Count(stack_id.c_str(), discard ? nullptr : m->pipeline_stack.back()); ++m->next_stack_id; m->pipeline_stack.emplace_back(c); m->pipeline = c; @@ -996,6 +997,12 @@ QPDFWriter::pushDiscardFilter(PipelinePopper& pp) } void +QPDFWriter::pushStringPipeline(PipelinePopper& pp, std::string& str) +{ + activatePipelineStack(pp, true, &str); +} + +void QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) { if (!m->id2.empty()) { @@ -1280,8 +1287,7 @@ QPDFWriter::willFilterStream( for (bool first_attempt: {true, false}) { PipelinePopper pp_stream_data(this); if (stream_data != nullptr) { - pushPipeline(new Pl_String("stream data", nullptr, *stream_data)); - activatePipelineStack(pp_stream_data); + pushStringPipeline(pp_stream_data, *stream_data); } else { pushDiscardFilter(pp_stream_data); } @@ -1644,9 +1650,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) { // Pass 1 PipelinePopper pp_ostream_pass1(this); - - pushPipeline(new Pl_String("object stream", nullptr, stream_buffer_pass1)); - activatePipelineStack(pp_ostream_pass1); + pushStringPipeline(pp_ostream_pass1, stream_buffer_pass1); int count = -1; for (auto const& obj: m->object_stream_to_objects[old_id]) { @@ -2888,9 +2892,8 @@ QPDFWriter::writeLinearized() // Write hint stream to a buffer { - pushPipeline(new Pl_String("hint buffer", nullptr, hint_buffer)); PipelinePopper pp_hint(this); - activatePipelineStack(pp_hint); + pushStringPipeline(pp_hint, hint_buffer); writeHintStream(hint_id); } hint_length = QIntC::to_offset(hint_buffer.size()); diff --git a/libqpdf/qpdf/Pipeline_private.hh b/libqpdf/qpdf/Pipeline_private.hh index 82042aa..4cc5823 100644 --- a/libqpdf/qpdf/Pipeline_private.hh +++ b/libqpdf/qpdf/Pipeline_private.hh @@ -13,12 +13,22 @@ namespace qpdf::pl { } + Count(char const* identifier, std::string* str) : + Pipeline(identifier, nullptr), + str(str) + { + } + ~Count() final = default; void write(unsigned char const* buf, size_t len) final { if (len) { + if (str) { + str->append(reinterpret_cast(buf), len); + return; + } count += static_cast(len); if (next()) { next()->write(buf, len); @@ -37,11 +47,12 @@ namespace qpdf::pl qpdf_offset_t getCount() const { - return count; + return str ? static_cast(str->size()) : count; } private: qpdf_offset_t count{0}; + std::string* str{nullptr}; }; } // namespace qpdf::pl