From 876c238ea9c6b307b95f838a5d34711a57265c07 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 23 Mar 2025 15:28:17 +0000 Subject: [PATCH] Add a private API version of Pl_Count --- include/qpdf/QPDFWriter.hh | 2 +- libqpdf/QPDFWriter.cc | 43 +++++++++++++++++++------------------------ libqpdf/QPDF_linearization.cc | 8 ++++---- libqpdf/qpdf/Pipeline_private.hh | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ libqpdf/qpdf/QPDFWriter_private.hh | 5 +++-- 5 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 libqpdf/qpdf/Pipeline_private.hh diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh index 748a945..ba08b88 100644 --- a/include/qpdf/QPDFWriter.hh +++ b/include/qpdf/QPDFWriter.hh @@ -597,7 +597,7 @@ 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&); + void activatePipelineStack(PipelinePopper& pp, bool discard = false); void initializePipelineStack(Pipeline*); void adjustAESStreamLength(size_t& length); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 793ea2e..5939cab 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -6,8 +6,6 @@ #include #include -#include -#include #include #include #include @@ -905,26 +903,26 @@ QPDFWriter::writePad(size_t nspaces) Pipeline* QPDFWriter::pushPipeline(Pipeline* p) { - qpdf_assert_debug(dynamic_cast(p) == nullptr); - m->pipeline_stack.push_back(p); + qpdf_assert_debug(!dynamic_cast(p)); + m->pipeline_stack.emplace_back(p); return p; } void QPDFWriter::initializePipelineStack(Pipeline* p) { - m->pipeline = new Pl_Count("pipeline stack base", p); - m->to_delete.push_back(std::shared_ptr(m->pipeline)); - m->pipeline_stack.push_back(m->pipeline); + m->pipeline = new pl::Count("pipeline stack base", p); + m->to_delete.emplace_back(std::shared_ptr(m->pipeline)); + m->pipeline_stack.emplace_back(m->pipeline); } void -QPDFWriter::activatePipelineStack(PipelinePopper& pp) +QPDFWriter::activatePipelineStack(PipelinePopper& pp, bool discard) { std::string stack_id("stack " + std::to_string(m->next_stack_id)); - auto* c = new Pl_Count(stack_id.c_str(), m->pipeline_stack.back()); + auto* c = new pl::Count(stack_id.c_str(), discard ? nullptr : m->pipeline_stack.back()); ++m->next_stack_id; - m->pipeline_stack.push_back(c); + m->pipeline_stack.emplace_back(c); m->pipeline = c; pp.stack_id = stack_id; } @@ -936,7 +934,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() } qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2); qw->m->pipeline->finish(); - qpdf_assert_debug(dynamic_cast(qw->m->pipeline_stack.back()) == qw->m->pipeline); + qpdf_assert_debug(dynamic_cast(qw->m->pipeline_stack.back()) == qw->m->pipeline); // It might be possible for this assertion to fail if writeLinearized exits by exception when // deterministic ID, but I don't think so. As of this writing, this is the only case in which // two dynamically allocated PipelinePopper objects ever exist at the same time, so the @@ -944,7 +942,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() qpdf_assert_debug(qw->m->pipeline->getIdentifier() == stack_id); delete qw->m->pipeline_stack.back(); qw->m->pipeline_stack.pop_back(); - while (dynamic_cast(qw->m->pipeline_stack.back()) == nullptr) { + while (!dynamic_cast(qw->m->pipeline_stack.back())) { Pipeline* p = qw->m->pipeline_stack.back(); if (dynamic_cast(p) == qw->m->md5_pipeline) { qw->m->md5_pipeline = nullptr; @@ -952,7 +950,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() qw->m->pipeline_stack.pop_back(); delete p; } - qw->m->pipeline = dynamic_cast(qw->m->pipeline_stack.back()); + qw->m->pipeline = dynamic_cast(qw->m->pipeline_stack.back()); } void @@ -994,8 +992,7 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) void QPDFWriter::pushDiscardFilter(PipelinePopper& pp) { - pushPipeline(new Pl_Discard()); - activatePipelineStack(pp); + activatePipelineStack(pp, true); } void @@ -1281,13 +1278,13 @@ QPDFWriter::willFilterStream( bool filtered = false; 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); } else { - pushPipeline(new Pl_Discard()); + pushDiscardFilter(pp_stream_data); } - PipelinePopper pp_stream_data(this); - activatePipelineStack(pp_stream_data); try { filtered = stream.pipeStreamData( m->pipeline, @@ -2678,8 +2675,8 @@ QPDFWriter::writeLinearized() // Write file in two passes. Part numbers refer to PDF spec 1.4. FILE* lin_pass1_file = nullptr; - auto pp_pass1 = std::make_shared(this); - auto pp_md5 = std::make_shared(this); + auto pp_pass1 = std::make_unique(this); + auto pp_md5 = std::make_unique(this); for (int pass: {1, 2}) { if (pass == 1) { if (!m->lin_pass1_filename.empty()) { @@ -3011,9 +3008,9 @@ QPDFWriter::registerProgressReporter(std::shared_ptr pr) void QPDFWriter::writeStandard() { - auto pp_md5 = std::make_shared(this); + auto pp_md5 = PipelinePopper(this); if (m->deterministic_id) { - pushMD5Pipeline(*pp_md5); + pushMD5Pipeline(pp_md5); } // Start writing @@ -3059,7 +3056,5 @@ QPDFWriter::writeStandard() "qpdf", "QPDFWriter standard deterministic ID", m->object_stream_to_objects.empty() ? 0 : 1); - pp_md5 = nullptr; - qpdf_assert_debug(m->md5_pipeline == nullptr); } } diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index 699977c..c307648 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -1757,13 +1757,13 @@ QPDF::generateHintStream( // can get offsets. Pl_String hint_stream("hint stream", nullptr, hint_buffer); Pipeline* next = &hint_stream; - std::shared_ptr flate; + std::unique_ptr flate; if (compressed) { flate = - std::make_shared("compress hint stream", &hint_stream, Pl_Flate::a_deflate); + std::make_unique("compress hint stream", &hint_stream, Pl_Flate::a_deflate); next = flate.get(); } - Pl_Count c("count", next); + pl::Count c("count", next); BitWriter w(&c); writeHPageOffset(w); diff --git a/libqpdf/qpdf/Pipeline_private.hh b/libqpdf/qpdf/Pipeline_private.hh new file mode 100644 index 0000000..82042aa --- /dev/null +++ b/libqpdf/qpdf/Pipeline_private.hh @@ -0,0 +1,48 @@ +#ifndef PIPELINE_PRIVATE_HH +#define PIPELINE_PRIVATE_HH + +#include + +namespace qpdf::pl +{ + class Count final: public Pipeline + { + public: + Count(char const* identifier, Pipeline* next) : + Pipeline(identifier, next) + { + } + + ~Count() final = default; + + void + write(unsigned char const* buf, size_t len) final + { + if (len) { + count += static_cast(len); + if (next()) { + next()->write(buf, len); + } + } + } + + void + finish() final + { + if (next()) { + next()->finish(); + } + } + + qpdf_offset_t + getCount() const + { + return count; + } + + private: + qpdf_offset_t count{0}; + }; +} // namespace qpdf::pl + +#endif // PIPELINE_PRIVATE_HH diff --git a/libqpdf/qpdf/QPDFWriter_private.hh b/libqpdf/qpdf/QPDFWriter_private.hh index cbb667f..c59ecf8 100644 --- a/libqpdf/qpdf/QPDFWriter_private.hh +++ b/libqpdf/qpdf/QPDFWriter_private.hh @@ -4,6 +4,7 @@ #include #include +#include // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization // only. @@ -98,7 +99,7 @@ class QPDFWriter::Members int encryption_dict_objid{0}; std::string cur_data_key; std::list> to_delete; - Pl_Count* pipeline{nullptr}; + qpdf::pl::Count* pipeline{nullptr}; std::vector object_queue; size_t object_queue_front{0}; QPDFWriter::ObjTable obj; @@ -112,7 +113,7 @@ class QPDFWriter::Members std::map page_object_to_seq; std::map contents_to_page_seq; std::map> object_stream_to_objects; - std::list pipeline_stack; + std::vector pipeline_stack; unsigned long long next_stack_id{0}; bool deterministic_id{false}; Pl_MD5* md5_pipeline{nullptr}; -- libgit2 0.21.4