Commit a78d18f7e7603965a6ff750dd79d8c8e38efb260

Authored by m-holger
1 parent 613c1221

Refactor `PipelinePopper` to add manual `pop` method and update its usage for si…

…mplified pipeline stack management in `QPDFWriter`.
Showing 1 changed file with 24 additions and 12 deletions
libqpdf/QPDFWriter.cc
@@ -95,6 +95,9 @@ class QPDFWriter::PipelinePopper @@ -95,6 +95,9 @@ class QPDFWriter::PipelinePopper
95 95
96 ~PipelinePopper(); 96 ~PipelinePopper();
97 97
  98 + // Manually pop pipeline from the pipeline stack.
  99 + void pop();
  100 +
98 Pl_stack* stack{nullptr}; 101 Pl_stack* stack{nullptr};
99 unsigned long stack_id{0}; 102 unsigned long stack_id{0};
100 }; 103 };
@@ -198,11 +201,10 @@ namespace @@ -198,11 +201,10 @@ namespace
198 qpdf_assert_debug(stack.size() >= 2); 201 qpdf_assert_debug(stack.size() >= 2);
199 top->finish(); 202 top->finish();
200 qpdf_assert_debug(dynamic_cast<pl::Count*>(stack.back()) == top); 203 qpdf_assert_debug(dynamic_cast<pl::Count*>(stack.back()) == top);
201 - // It might be possible for this assertion to fail if writeLinearized exits by exception  
202 - // when deterministic ID, but I don't think so. As of this writing, this is the only  
203 - // case in which two dynamically allocated PipelinePopper objects ever exist at the same  
204 - // time, so the assertion will fail if they get popped out of order from automatic  
205 - // destruction. 204 + // It used to be possible for this assertion to fail if writeLinearized exits by
  205 + // exception when deterministic ID. There are no longer any cases in which two
  206 + // dynamically allocated PipelinePopper objects ever exist at the same time, so the
  207 + // assertion will fail if they get popped out of order from automatic destruction.
206 qpdf_assert_debug(top->id() == stack_id); 208 qpdf_assert_debug(top->id() == stack_id);
207 delete stack.back(); 209 delete stack.back();
208 stack.pop_back(); 210 stack.pop_back();
@@ -240,6 +242,16 @@ QPDFWriter::PipelinePopper::~PipelinePopper() @@ -240,6 +242,16 @@ QPDFWriter::PipelinePopper::~PipelinePopper()
240 } 242 }
241 } 243 }
242 244
  245 +void
  246 +QPDFWriter::PipelinePopper::pop()
  247 +{
  248 + if (stack) {
  249 + stack->pop(stack_id);
  250 + }
  251 + stack_id = 0;
  252 + stack = nullptr;
  253 +}
  254 +
243 class QPDFWriter::Members 255 class QPDFWriter::Members
244 { 256 {
245 friend class QPDFWriter; 257 friend class QPDFWriter;
@@ -2762,19 +2774,19 @@ QPDFWriter::writeLinearized() @@ -2762,19 +2774,19 @@ QPDFWriter::writeLinearized()
2762 // Write file in two passes. Part numbers refer to PDF spec 1.4. 2774 // Write file in two passes. Part numbers refer to PDF spec 1.4.
2763 2775
2764 FILE* lin_pass1_file = nullptr; 2776 FILE* lin_pass1_file = nullptr;
2765 - auto pp_pass1 = std::make_unique<PipelinePopper>(m->pipeline_stack);  
2766 - auto pp_md5 = std::make_unique<PipelinePopper>(m->pipeline_stack); 2777 + auto pp_pass1 = m->pipeline_stack.popper();
  2778 + auto pp_md5 = m->pipeline_stack.popper();
2767 for (int pass: {1, 2}) { 2779 for (int pass: {1, 2}) {
2768 if (pass == 1) { 2780 if (pass == 1) {
2769 if (!m->lin_pass1_filename.empty()) { 2781 if (!m->lin_pass1_filename.empty()) {
2770 lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb"); 2782 lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb");
2771 m->pipeline_stack.push(new Pl_StdioFile("linearization pass1", lin_pass1_file)); 2783 m->pipeline_stack.push(new Pl_StdioFile("linearization pass1", lin_pass1_file));
2772 - m->pipeline_stack.activate(*pp_pass1); 2784 + m->pipeline_stack.activate(pp_pass1);
2773 } else { 2785 } else {
2774 - m->pipeline_stack.activate(*pp_pass1, true); 2786 + m->pipeline_stack.activate(pp_pass1, true);
2775 } 2787 }
2776 if (m->deterministic_id) { 2788 if (m->deterministic_id) {
2777 - pushMD5Pipeline(*pp_md5); 2789 + pushMD5Pipeline(pp_md5);
2778 } 2790 }
2779 } 2791 }
2780 2792
@@ -2949,13 +2961,13 @@ QPDFWriter::writeLinearized() @@ -2949,13 +2961,13 @@ QPDFWriter::writeLinearized()
2949 if (m->deterministic_id) { 2961 if (m->deterministic_id) {
2950 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); 2962 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
2951 computeDeterministicIDData(); 2963 computeDeterministicIDData();
2952 - pp_md5 = nullptr; 2964 + pp_md5.pop();
2953 qpdf_assert_debug(m->md5_pipeline == nullptr); 2965 qpdf_assert_debug(m->md5_pipeline == nullptr);
2954 } 2966 }
2955 2967
2956 // Close first pass pipeline 2968 // Close first pass pipeline
2957 file_size = m->pipeline->getCount(); 2969 file_size = m->pipeline->getCount();
2958 - pp_pass1 = nullptr; 2970 + pp_pass1.pop();
2959 2971
2960 // Save hint offset since it will be set to zero by calling openObject. 2972 // Save hint offset since it will be set to zero by calling openObject.
2961 qpdf_offset_t hint_offset1 = m->new_obj[hint_id].xref.getOffset(); 2973 qpdf_offset_t hint_offset1 = m->new_obj[hint_id].xref.getOffset();