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 95  
96 96 ~PipelinePopper();
97 97  
  98 + // Manually pop pipeline from the pipeline stack.
  99 + void pop();
  100 +
98 101 Pl_stack* stack{nullptr};
99 102 unsigned long stack_id{0};
100 103 };
... ... @@ -198,11 +201,10 @@ namespace
198 201 qpdf_assert_debug(stack.size() >= 2);
199 202 top->finish();
200 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 208 qpdf_assert_debug(top->id() == stack_id);
207 209 delete stack.back();
208 210 stack.pop_back();
... ... @@ -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 255 class QPDFWriter::Members
244 256 {
245 257 friend class QPDFWriter;
... ... @@ -2762,19 +2774,19 @@ QPDFWriter::writeLinearized()
2762 2774 // Write file in two passes. Part numbers refer to PDF spec 1.4.
2763 2775  
2764 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 2779 for (int pass: {1, 2}) {
2768 2780 if (pass == 1) {
2769 2781 if (!m->lin_pass1_filename.empty()) {
2770 2782 lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb");
2771 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 2785 } else {
2774   - m->pipeline_stack.activate(*pp_pass1, true);
  2786 + m->pipeline_stack.activate(pp_pass1, true);
2775 2787 }
2776 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 2961 if (m->deterministic_id) {
2950 2962 QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1);
2951 2963 computeDeterministicIDData();
2952   - pp_md5 = nullptr;
  2964 + pp_md5.pop();
2953 2965 qpdf_assert_debug(m->md5_pipeline == nullptr);
2954 2966 }
2955 2967  
2956 2968 // Close first pass pipeline
2957 2969 file_size = m->pipeline->getCount();
2958   - pp_pass1 = nullptr;
  2970 + pp_pass1.pop();
2959 2971  
2960 2972 // Save hint offset since it will be set to zero by calling openObject.
2961 2973 qpdf_offset_t hint_offset1 = m->new_obj[hint_id].xref.getOffset();
... ...