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,7 +570,6 @@ class QPDFWriter
570 // is popped. 570 // is popped.
571 571
572 void adjustAESStreamLength(size_t& length); 572 void adjustAESStreamLength(size_t& length);
573 - void pushMD5Pipeline(PipelinePopper&);  
574 void computeDeterministicIDData(); 573 void computeDeterministicIDData();
575 574
576 class Members; 575 class Members;
libqpdf/QPDFWriter.cc
@@ -109,7 +109,7 @@ namespace @@ -109,7 +109,7 @@ namespace
109 using PP = QPDFWriter::PipelinePopper; 109 using PP = QPDFWriter::PipelinePopper;
110 110
111 public: 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 top(top), 113 top(top),
114 md5_pipeline(md5_pipeline) 114 md5_pipeline(md5_pipeline)
115 { 115 {
@@ -183,12 +183,21 @@ namespace @@ -183,12 +183,21 @@ namespace
183 top = c; 183 top = c;
184 ++next_stack_id; 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 void 203 void
@@ -205,16 +214,17 @@ namespace @@ -205,16 +214,17 @@ namespace
205 // exception when deterministic ID. There are no longer any cases in which two 214 // 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 215 // 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. 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 qpdf_assert_debug(top->id() == stack_id); 221 qpdf_assert_debug(top->id() == stack_id);
209 delete stack.back(); 222 delete stack.back();
210 stack.pop_back(); 223 stack.pop_back();
  224 +
211 while (!dynamic_cast<pl::Count*>(stack.back())) { 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 stack.pop_back(); 227 stack.pop_back();
217 - delete p;  
218 } 228 }
219 top = dynamic_cast<pl::Count*>(stack.back()); 229 top = dynamic_cast<pl::Count*>(stack.back());
220 } 230 }
@@ -228,9 +238,10 @@ namespace @@ -228,9 +238,10 @@ namespace
228 private: 238 private:
229 std::vector<Pipeline*> stack; 239 std::vector<Pipeline*> stack;
230 pl::Count*& top; 240 pl::Count*& top;
231 - Pl_MD5*& md5_pipeline; 241 + std::unique_ptr<Pl_MD5>& md5_pipeline;
232 std::vector<std::unique_ptr<Pipeline>> to_delete; 242 std::vector<std::unique_ptr<Pipeline>> to_delete;
233 unsigned long next_stack_id{2}; 243 unsigned long next_stack_id{2};
  244 + unsigned long md5_id{0};
234 std::string count_buffer; 245 std::string count_buffer;
235 }; 246 };
236 } // namespace 247 } // namespace
@@ -320,7 +331,7 @@ class QPDFWriter::Members @@ -320,7 +331,7 @@ class QPDFWriter::Members
320 std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects; 331 std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects;
321 Pl_stack pipeline_stack; 332 Pl_stack pipeline_stack;
322 bool deterministic_id{false}; 333 bool deterministic_id{false};
323 - Pl_MD5* md5_pipeline{nullptr}; 334 + std::unique_ptr<Pl_MD5> md5_pipeline{nullptr};
324 std::string deterministic_id_data; 335 std::string deterministic_id_data;
325 bool did_write_setup{false}; 336 bool did_write_setup{false};
326 337
@@ -1122,26 +1133,13 @@ QPDFWriter::write_encrypted(std::string_view str) @@ -1122,26 +1133,13 @@ QPDFWriter::write_encrypted(std::string_view str)
1122 } 1133 }
1123 1134
1124 void 1135 void
1125 -QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) 1136 +QPDFWriter::computeDeterministicIDData()
1126 { 1137 {
1127 if (!m->id2.empty()) { 1138 if (!m->id2.empty()) {
1128 // Can't happen in the code 1139 // Can't happen in the code
1129 throw std::logic_error( 1140 throw std::logic_error(
1130 "Deterministic ID computation enabled after ID generation has already occurred."); 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 qpdf_assert_debug(m->md5_pipeline != nullptr); 1143 qpdf_assert_debug(m->md5_pipeline != nullptr);
1146 qpdf_assert_debug(m->deterministic_id_data.empty()); 1144 qpdf_assert_debug(m->deterministic_id_data.empty());
1147 m->deterministic_id_data = m->md5_pipeline->getHexDigest(); 1145 m->deterministic_id_data = m->md5_pipeline->getHexDigest();
@@ -2760,7 +2758,7 @@ QPDFWriter::writeLinearized() @@ -2760,7 +2758,7 @@ QPDFWriter::writeLinearized()
2760 m->pipeline_stack.activate(pp_pass1, true); 2758 m->pipeline_stack.activate(pp_pass1, true);
2761 } 2759 }
2762 if (m->deterministic_id) { 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,7 +3066,7 @@ QPDFWriter::writeStandard()
3068 { 3066 {
3069 auto pp_md5 = m->pipeline_stack.popper(); 3067 auto pp_md5 = m->pipeline_stack.popper();
3070 if (m->deterministic_id) { 3068 if (m->deterministic_id) {
3071 - pushMD5Pipeline(pp_md5); 3069 + m->pipeline_stack.activate_md5(pp_md5);
3072 } 3070 }
3073 3071
3074 // Start writing 3072 // Start writing