Commit 63dae8eccd7aba882675e7b9635917f026d47b08
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.
Showing
2 changed files
with
27 additions
and
30 deletions
include/qpdf/QPDFWriter.hh
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 | ... | ... |