Commit 63dae8eccd7aba882675e7b9635917f026d47b08

Authored by m-holger
1 parent a48eae3c

Refactor `QPDFWriter` pipeline stack logic to use `std::unique_ptr` for `Pl_MD5`…

…, improving encapsulation and memory management. Remove the now redundant `pushMD5Pipeline` method and streamline MD5 activation.
include/qpdf/QPDFWriter.hh
... ... @@ -570,7 +570,6 @@ class QPDFWriter
570 570 // is popped.
571 571  
572 572 void adjustAESStreamLength(size_t& length);
573   - void pushMD5Pipeline(PipelinePopper&);
574 573 void computeDeterministicIDData();
575 574  
576 575 class Members;
... ...
libqpdf/QPDFWriter.cc
... ... @@ -109,7 +109,7 @@ namespace
109 109 using PP = QPDFWriter::PipelinePopper;
110 110  
111 111 public:
112   - Pl_stack(pl::Count*& top, Pl_MD5*& md5_pipeline) :
  112 + Pl_stack(pl::Count*& top, std::unique_ptr<Pl_MD5>& md5_pipeline) :
113 113 top(top),
114 114 md5_pipeline(md5_pipeline)
115 115 {
... ... @@ -183,12 +183,21 @@ namespace
183 183 top = c;
184 184 ++next_stack_id;
185 185 }
186   - Pipeline*
187   - push(Pipeline* p)
  186 + void
  187 + activate_md5(PP& pp)
188 188 {
189   - qpdf_assert_debug(!dynamic_cast<pl::Count*>(p));
190   - stack.emplace_back(p);
191   - return p;
  189 + qpdf_assert_debug(!md5_pipeline);
  190 + qpdf_assert_debug(md5_id == 0);
  191 + qpdf_assert_debug(top->getCount() == 0);
  192 + md5_pipeline = std::make_unique<Pl_MD5>("qpdf md5", top);
  193 + md5_pipeline->persistAcrossFinish(true);
  194 + // Special case code in pop clears m->md5_pipeline upon deletion.
  195 + auto* c = new pl::Count(next_stack_id, md5_pipeline.get());
  196 + pp.stack_id = next_stack_id;
  197 + md5_id = next_stack_id;
  198 + stack.emplace_back(c);
  199 + top = c;
  200 + ++next_stack_id;
192 201 }
193 202  
194 203 void
... ... @@ -205,16 +214,17 @@ namespace
205 214 // exception when deterministic ID. There are no longer any cases in which two
206 215 // dynamically allocated PipelinePopper objects ever exist at the same time, so the
207 216 // assertion will fail if they get popped out of order from automatic destruction.
  217 + if (stack_id == md5_id) {
  218 + md5_pipeline = nullptr;
  219 + md5_id = 0;
  220 + }
208 221 qpdf_assert_debug(top->id() == stack_id);
209 222 delete stack.back();
210 223 stack.pop_back();
  224 +
211 225 while (!dynamic_cast<pl::Count*>(stack.back())) {
212   - Pipeline* p = stack.back();
213   - if (dynamic_cast<Pl_MD5*>(p) == md5_pipeline) {
214   - md5_pipeline = nullptr;
215   - }
  226 + delete stack.back();
216 227 stack.pop_back();
217   - delete p;
218 228 }
219 229 top = dynamic_cast<pl::Count*>(stack.back());
220 230 }
... ... @@ -228,9 +238,10 @@ namespace
228 238 private:
229 239 std::vector<Pipeline*> stack;
230 240 pl::Count*& top;
231   - Pl_MD5*& md5_pipeline;
  241 + std::unique_ptr<Pl_MD5>& md5_pipeline;
232 242 std::vector<std::unique_ptr<Pipeline>> to_delete;
233 243 unsigned long next_stack_id{2};
  244 + unsigned long md5_id{0};
234 245 std::string count_buffer;
235 246 };
236 247 } // namespace
... ... @@ -320,7 +331,7 @@ class QPDFWriter::Members
320 331 std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects;
321 332 Pl_stack pipeline_stack;
322 333 bool deterministic_id{false};
323   - Pl_MD5* md5_pipeline{nullptr};
  334 + std::unique_ptr<Pl_MD5> md5_pipeline{nullptr};
324 335 std::string deterministic_id_data;
325 336 bool did_write_setup{false};
326 337  
... ... @@ -1122,26 +1133,13 @@ QPDFWriter::write_encrypted(std::string_view str)
1122 1133 }
1123 1134  
1124 1135 void
1125   -QPDFWriter::pushMD5Pipeline(PipelinePopper& pp)
  1136 +QPDFWriter::computeDeterministicIDData()
1126 1137 {
1127 1138 if (!m->id2.empty()) {
1128 1139 // Can't happen in the code
1129 1140 throw std::logic_error(
1130 1141 "Deterministic ID computation enabled after ID generation has already occurred.");
1131 1142 }
1132   - qpdf_assert_debug(m->deterministic_id);
1133   - qpdf_assert_debug(m->md5_pipeline == nullptr);
1134   - qpdf_assert_debug(m->pipeline->getCount() == 0);
1135   - m->md5_pipeline = new Pl_MD5("qpdf md5", m->pipeline);
1136   - m->md5_pipeline->persistAcrossFinish(true);
1137   - // Special case code in popPipelineStack clears m->md5_pipeline upon deletion.
1138   - m->pipeline_stack.push(m->md5_pipeline);
1139   - m->pipeline_stack.activate(pp);
1140   -}
1141   -
1142   -void
1143   -QPDFWriter::computeDeterministicIDData()
1144   -{
1145 1143 qpdf_assert_debug(m->md5_pipeline != nullptr);
1146 1144 qpdf_assert_debug(m->deterministic_id_data.empty());
1147 1145 m->deterministic_id_data = m->md5_pipeline->getHexDigest();
... ... @@ -2760,7 +2758,7 @@ QPDFWriter::writeLinearized()
2760 2758 m->pipeline_stack.activate(pp_pass1, true);
2761 2759 }
2762 2760 if (m->deterministic_id) {
2763   - pushMD5Pipeline(pp_md5);
  2761 + m->pipeline_stack.activate_md5(pp_md5);
2764 2762 }
2765 2763 }
2766 2764  
... ... @@ -3068,7 +3066,7 @@ QPDFWriter::writeStandard()
3068 3066 {
3069 3067 auto pp_md5 = m->pipeline_stack.popper();
3070 3068 if (m->deterministic_id) {
3071   - pushMD5Pipeline(pp_md5);
  3069 + m->pipeline_stack.activate_md5(pp_md5);
3072 3070 }
3073 3071  
3074 3072 // Start writing
... ...