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
| @@ -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 |