Commit a78d18f7e7603965a6ff750dd79d8c8e38efb260
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(); |