Commit 876c238ea9c6b307b95f838a5d34711a57265c07
1 parent
05f8281f
Add a private API version of Pl_Count
... and use it in QPDFWriter and QPDF::generateHintStream.
Showing
5 changed files
with
75 additions
and
31 deletions
include/qpdf/QPDFWriter.hh
| @@ -597,7 +597,7 @@ class QPDFWriter | @@ -597,7 +597,7 @@ class QPDFWriter | ||
| 597 | // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack | 597 | // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack |
| 598 | // is popped. | 598 | // is popped. |
| 599 | Pipeline* pushPipeline(Pipeline*); | 599 | Pipeline* pushPipeline(Pipeline*); |
| 600 | - void activatePipelineStack(PipelinePopper&); | 600 | + void activatePipelineStack(PipelinePopper& pp, bool discard = false); |
| 601 | void initializePipelineStack(Pipeline*); | 601 | void initializePipelineStack(Pipeline*); |
| 602 | 602 | ||
| 603 | void adjustAESStreamLength(size_t& length); | 603 | void adjustAESStreamLength(size_t& length); |
libqpdf/QPDFWriter.cc
| @@ -6,8 +6,6 @@ | @@ -6,8 +6,6 @@ | ||
| 6 | 6 | ||
| 7 | #include <qpdf/MD5.hh> | 7 | #include <qpdf/MD5.hh> |
| 8 | #include <qpdf/Pl_AES_PDF.hh> | 8 | #include <qpdf/Pl_AES_PDF.hh> |
| 9 | -#include <qpdf/Pl_Count.hh> | ||
| 10 | -#include <qpdf/Pl_Discard.hh> | ||
| 11 | #include <qpdf/Pl_Flate.hh> | 9 | #include <qpdf/Pl_Flate.hh> |
| 12 | #include <qpdf/Pl_MD5.hh> | 10 | #include <qpdf/Pl_MD5.hh> |
| 13 | #include <qpdf/Pl_PNGFilter.hh> | 11 | #include <qpdf/Pl_PNGFilter.hh> |
| @@ -905,26 +903,26 @@ QPDFWriter::writePad(size_t nspaces) | @@ -905,26 +903,26 @@ QPDFWriter::writePad(size_t nspaces) | ||
| 905 | Pipeline* | 903 | Pipeline* |
| 906 | QPDFWriter::pushPipeline(Pipeline* p) | 904 | QPDFWriter::pushPipeline(Pipeline* p) |
| 907 | { | 905 | { |
| 908 | - qpdf_assert_debug(dynamic_cast<Pl_Count*>(p) == nullptr); | ||
| 909 | - m->pipeline_stack.push_back(p); | 906 | + qpdf_assert_debug(!dynamic_cast<pl::Count*>(p)); |
| 907 | + m->pipeline_stack.emplace_back(p); | ||
| 910 | return p; | 908 | return p; |
| 911 | } | 909 | } |
| 912 | 910 | ||
| 913 | void | 911 | void |
| 914 | QPDFWriter::initializePipelineStack(Pipeline* p) | 912 | QPDFWriter::initializePipelineStack(Pipeline* p) |
| 915 | { | 913 | { |
| 916 | - m->pipeline = new Pl_Count("pipeline stack base", p); | ||
| 917 | - m->to_delete.push_back(std::shared_ptr<Pipeline>(m->pipeline)); | ||
| 918 | - m->pipeline_stack.push_back(m->pipeline); | 914 | + m->pipeline = new pl::Count("pipeline stack base", p); |
| 915 | + m->to_delete.emplace_back(std::shared_ptr<Pipeline>(m->pipeline)); | ||
| 916 | + m->pipeline_stack.emplace_back(m->pipeline); | ||
| 919 | } | 917 | } |
| 920 | 918 | ||
| 921 | void | 919 | void |
| 922 | -QPDFWriter::activatePipelineStack(PipelinePopper& pp) | 920 | +QPDFWriter::activatePipelineStack(PipelinePopper& pp, bool discard) |
| 923 | { | 921 | { |
| 924 | std::string stack_id("stack " + std::to_string(m->next_stack_id)); | 922 | std::string stack_id("stack " + std::to_string(m->next_stack_id)); |
| 925 | - auto* c = new Pl_Count(stack_id.c_str(), m->pipeline_stack.back()); | 923 | + auto* c = new pl::Count(stack_id.c_str(), discard ? nullptr : m->pipeline_stack.back()); |
| 926 | ++m->next_stack_id; | 924 | ++m->next_stack_id; |
| 927 | - m->pipeline_stack.push_back(c); | 925 | + m->pipeline_stack.emplace_back(c); |
| 928 | m->pipeline = c; | 926 | m->pipeline = c; |
| 929 | pp.stack_id = stack_id; | 927 | pp.stack_id = stack_id; |
| 930 | } | 928 | } |
| @@ -936,7 +934,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | @@ -936,7 +934,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | ||
| 936 | } | 934 | } |
| 937 | qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2); | 935 | qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2); |
| 938 | qw->m->pipeline->finish(); | 936 | qw->m->pipeline->finish(); |
| 939 | - qpdf_assert_debug(dynamic_cast<Pl_Count*>(qw->m->pipeline_stack.back()) == qw->m->pipeline); | 937 | + qpdf_assert_debug(dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back()) == qw->m->pipeline); |
| 940 | // It might be possible for this assertion to fail if writeLinearized exits by exception when | 938 | // It might be possible for this assertion to fail if writeLinearized exits by exception when |
| 941 | // deterministic ID, but I don't think so. As of this writing, this is the only case in which | 939 | // deterministic ID, but I don't think so. As of this writing, this is the only case in which |
| 942 | // two dynamically allocated PipelinePopper objects ever exist at the same time, so the | 940 | // two dynamically allocated PipelinePopper objects ever exist at the same time, so the |
| @@ -944,7 +942,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | @@ -944,7 +942,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | ||
| 944 | qpdf_assert_debug(qw->m->pipeline->getIdentifier() == stack_id); | 942 | qpdf_assert_debug(qw->m->pipeline->getIdentifier() == stack_id); |
| 945 | delete qw->m->pipeline_stack.back(); | 943 | delete qw->m->pipeline_stack.back(); |
| 946 | qw->m->pipeline_stack.pop_back(); | 944 | qw->m->pipeline_stack.pop_back(); |
| 947 | - while (dynamic_cast<Pl_Count*>(qw->m->pipeline_stack.back()) == nullptr) { | 945 | + while (!dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back())) { |
| 948 | Pipeline* p = qw->m->pipeline_stack.back(); | 946 | Pipeline* p = qw->m->pipeline_stack.back(); |
| 949 | if (dynamic_cast<Pl_MD5*>(p) == qw->m->md5_pipeline) { | 947 | if (dynamic_cast<Pl_MD5*>(p) == qw->m->md5_pipeline) { |
| 950 | qw->m->md5_pipeline = nullptr; | 948 | qw->m->md5_pipeline = nullptr; |
| @@ -952,7 +950,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | @@ -952,7 +950,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper() | ||
| 952 | qw->m->pipeline_stack.pop_back(); | 950 | qw->m->pipeline_stack.pop_back(); |
| 953 | delete p; | 951 | delete p; |
| 954 | } | 952 | } |
| 955 | - qw->m->pipeline = dynamic_cast<Pl_Count*>(qw->m->pipeline_stack.back()); | 953 | + qw->m->pipeline = dynamic_cast<pl::Count*>(qw->m->pipeline_stack.back()); |
| 956 | } | 954 | } |
| 957 | 955 | ||
| 958 | void | 956 | void |
| @@ -994,8 +992,7 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) | @@ -994,8 +992,7 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) | ||
| 994 | void | 992 | void |
| 995 | QPDFWriter::pushDiscardFilter(PipelinePopper& pp) | 993 | QPDFWriter::pushDiscardFilter(PipelinePopper& pp) |
| 996 | { | 994 | { |
| 997 | - pushPipeline(new Pl_Discard()); | ||
| 998 | - activatePipelineStack(pp); | 995 | + activatePipelineStack(pp, true); |
| 999 | } | 996 | } |
| 1000 | 997 | ||
| 1001 | void | 998 | void |
| @@ -1281,13 +1278,13 @@ QPDFWriter::willFilterStream( | @@ -1281,13 +1278,13 @@ QPDFWriter::willFilterStream( | ||
| 1281 | 1278 | ||
| 1282 | bool filtered = false; | 1279 | bool filtered = false; |
| 1283 | for (bool first_attempt: {true, false}) { | 1280 | for (bool first_attempt: {true, false}) { |
| 1281 | + PipelinePopper pp_stream_data(this); | ||
| 1284 | if (stream_data != nullptr) { | 1282 | if (stream_data != nullptr) { |
| 1285 | pushPipeline(new Pl_String("stream data", nullptr, *stream_data)); | 1283 | pushPipeline(new Pl_String("stream data", nullptr, *stream_data)); |
| 1284 | + activatePipelineStack(pp_stream_data); | ||
| 1286 | } else { | 1285 | } else { |
| 1287 | - pushPipeline(new Pl_Discard()); | 1286 | + pushDiscardFilter(pp_stream_data); |
| 1288 | } | 1287 | } |
| 1289 | - PipelinePopper pp_stream_data(this); | ||
| 1290 | - activatePipelineStack(pp_stream_data); | ||
| 1291 | try { | 1288 | try { |
| 1292 | filtered = stream.pipeStreamData( | 1289 | filtered = stream.pipeStreamData( |
| 1293 | m->pipeline, | 1290 | m->pipeline, |
| @@ -2678,8 +2675,8 @@ QPDFWriter::writeLinearized() | @@ -2678,8 +2675,8 @@ QPDFWriter::writeLinearized() | ||
| 2678 | // Write file in two passes. Part numbers refer to PDF spec 1.4. | 2675 | // Write file in two passes. Part numbers refer to PDF spec 1.4. |
| 2679 | 2676 | ||
| 2680 | FILE* lin_pass1_file = nullptr; | 2677 | FILE* lin_pass1_file = nullptr; |
| 2681 | - auto pp_pass1 = std::make_shared<PipelinePopper>(this); | ||
| 2682 | - auto pp_md5 = std::make_shared<PipelinePopper>(this); | 2678 | + auto pp_pass1 = std::make_unique<PipelinePopper>(this); |
| 2679 | + auto pp_md5 = std::make_unique<PipelinePopper>(this); | ||
| 2683 | for (int pass: {1, 2}) { | 2680 | for (int pass: {1, 2}) { |
| 2684 | if (pass == 1) { | 2681 | if (pass == 1) { |
| 2685 | if (!m->lin_pass1_filename.empty()) { | 2682 | if (!m->lin_pass1_filename.empty()) { |
| @@ -3011,9 +3008,9 @@ QPDFWriter::registerProgressReporter(std::shared_ptr<ProgressReporter> pr) | @@ -3011,9 +3008,9 @@ QPDFWriter::registerProgressReporter(std::shared_ptr<ProgressReporter> pr) | ||
| 3011 | void | 3008 | void |
| 3012 | QPDFWriter::writeStandard() | 3009 | QPDFWriter::writeStandard() |
| 3013 | { | 3010 | { |
| 3014 | - auto pp_md5 = std::make_shared<PipelinePopper>(this); | 3011 | + auto pp_md5 = PipelinePopper(this); |
| 3015 | if (m->deterministic_id) { | 3012 | if (m->deterministic_id) { |
| 3016 | - pushMD5Pipeline(*pp_md5); | 3013 | + pushMD5Pipeline(pp_md5); |
| 3017 | } | 3014 | } |
| 3018 | 3015 | ||
| 3019 | // Start writing | 3016 | // Start writing |
| @@ -3059,7 +3056,5 @@ QPDFWriter::writeStandard() | @@ -3059,7 +3056,5 @@ QPDFWriter::writeStandard() | ||
| 3059 | "qpdf", | 3056 | "qpdf", |
| 3060 | "QPDFWriter standard deterministic ID", | 3057 | "QPDFWriter standard deterministic ID", |
| 3061 | m->object_stream_to_objects.empty() ? 0 : 1); | 3058 | m->object_stream_to_objects.empty() ? 0 : 1); |
| 3062 | - pp_md5 = nullptr; | ||
| 3063 | - qpdf_assert_debug(m->md5_pipeline == nullptr); | ||
| 3064 | } | 3059 | } |
| 3065 | } | 3060 | } |
libqpdf/QPDF_linearization.cc
| @@ -5,8 +5,8 @@ | @@ -5,8 +5,8 @@ | ||
| 5 | #include <qpdf/BitStream.hh> | 5 | #include <qpdf/BitStream.hh> |
| 6 | #include <qpdf/BitWriter.hh> | 6 | #include <qpdf/BitWriter.hh> |
| 7 | #include <qpdf/InputSource_private.hh> | 7 | #include <qpdf/InputSource_private.hh> |
| 8 | +#include <qpdf/Pipeline_private.hh> | ||
| 8 | #include <qpdf/Pl_Buffer.hh> | 9 | #include <qpdf/Pl_Buffer.hh> |
| 9 | -#include <qpdf/Pl_Count.hh> | ||
| 10 | #include <qpdf/Pl_Flate.hh> | 10 | #include <qpdf/Pl_Flate.hh> |
| 11 | #include <qpdf/Pl_String.hh> | 11 | #include <qpdf/Pl_String.hh> |
| 12 | #include <qpdf/QPDFExc.hh> | 12 | #include <qpdf/QPDFExc.hh> |
| @@ -1757,13 +1757,13 @@ QPDF::generateHintStream( | @@ -1757,13 +1757,13 @@ QPDF::generateHintStream( | ||
| 1757 | // can get offsets. | 1757 | // can get offsets. |
| 1758 | Pl_String hint_stream("hint stream", nullptr, hint_buffer); | 1758 | Pl_String hint_stream("hint stream", nullptr, hint_buffer); |
| 1759 | Pipeline* next = &hint_stream; | 1759 | Pipeline* next = &hint_stream; |
| 1760 | - std::shared_ptr<Pipeline> flate; | 1760 | + std::unique_ptr<Pipeline> flate; |
| 1761 | if (compressed) { | 1761 | if (compressed) { |
| 1762 | flate = | 1762 | flate = |
| 1763 | - std::make_shared<Pl_Flate>("compress hint stream", &hint_stream, Pl_Flate::a_deflate); | 1763 | + std::make_unique<Pl_Flate>("compress hint stream", &hint_stream, Pl_Flate::a_deflate); |
| 1764 | next = flate.get(); | 1764 | next = flate.get(); |
| 1765 | } | 1765 | } |
| 1766 | - Pl_Count c("count", next); | 1766 | + pl::Count c("count", next); |
| 1767 | BitWriter w(&c); | 1767 | BitWriter w(&c); |
| 1768 | 1768 | ||
| 1769 | writeHPageOffset(w); | 1769 | writeHPageOffset(w); |
libqpdf/qpdf/Pipeline_private.hh
0 → 100644
| 1 | +#ifndef PIPELINE_PRIVATE_HH | ||
| 2 | +#define PIPELINE_PRIVATE_HH | ||
| 3 | + | ||
| 4 | +#include <qpdf/Pipeline.hh> | ||
| 5 | + | ||
| 6 | +namespace qpdf::pl | ||
| 7 | +{ | ||
| 8 | + class Count final: public Pipeline | ||
| 9 | + { | ||
| 10 | + public: | ||
| 11 | + Count(char const* identifier, Pipeline* next) : | ||
| 12 | + Pipeline(identifier, next) | ||
| 13 | + { | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + ~Count() final = default; | ||
| 17 | + | ||
| 18 | + void | ||
| 19 | + write(unsigned char const* buf, size_t len) final | ||
| 20 | + { | ||
| 21 | + if (len) { | ||
| 22 | + count += static_cast<qpdf_offset_t>(len); | ||
| 23 | + if (next()) { | ||
| 24 | + next()->write(buf, len); | ||
| 25 | + } | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + void | ||
| 30 | + finish() final | ||
| 31 | + { | ||
| 32 | + if (next()) { | ||
| 33 | + next()->finish(); | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + qpdf_offset_t | ||
| 38 | + getCount() const | ||
| 39 | + { | ||
| 40 | + return count; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + private: | ||
| 44 | + qpdf_offset_t count{0}; | ||
| 45 | + }; | ||
| 46 | +} // namespace qpdf::pl | ||
| 47 | + | ||
| 48 | +#endif // PIPELINE_PRIVATE_HH |
libqpdf/qpdf/QPDFWriter_private.hh
| @@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
| 4 | #include <qpdf/QPDFWriter.hh> | 4 | #include <qpdf/QPDFWriter.hh> |
| 5 | 5 | ||
| 6 | #include <qpdf/ObjTable.hh> | 6 | #include <qpdf/ObjTable.hh> |
| 7 | +#include <qpdf/Pipeline_private.hh> | ||
| 7 | 8 | ||
| 8 | // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization | 9 | // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization |
| 9 | // only. | 10 | // only. |
| @@ -98,7 +99,7 @@ class QPDFWriter::Members | @@ -98,7 +99,7 @@ class QPDFWriter::Members | ||
| 98 | int encryption_dict_objid{0}; | 99 | int encryption_dict_objid{0}; |
| 99 | std::string cur_data_key; | 100 | std::string cur_data_key; |
| 100 | std::list<std::shared_ptr<Pipeline>> to_delete; | 101 | std::list<std::shared_ptr<Pipeline>> to_delete; |
| 101 | - Pl_Count* pipeline{nullptr}; | 102 | + qpdf::pl::Count* pipeline{nullptr}; |
| 102 | std::vector<QPDFObjectHandle> object_queue; | 103 | std::vector<QPDFObjectHandle> object_queue; |
| 103 | size_t object_queue_front{0}; | 104 | size_t object_queue_front{0}; |
| 104 | QPDFWriter::ObjTable obj; | 105 | QPDFWriter::ObjTable obj; |
| @@ -112,7 +113,7 @@ class QPDFWriter::Members | @@ -112,7 +113,7 @@ class QPDFWriter::Members | ||
| 112 | std::map<QPDFObjGen, int> page_object_to_seq; | 113 | std::map<QPDFObjGen, int> page_object_to_seq; |
| 113 | std::map<QPDFObjGen, int> contents_to_page_seq; | 114 | std::map<QPDFObjGen, int> contents_to_page_seq; |
| 114 | std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects; | 115 | std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects; |
| 115 | - std::list<Pipeline*> pipeline_stack; | 116 | + std::vector<Pipeline*> pipeline_stack; |
| 116 | unsigned long long next_stack_id{0}; | 117 | unsigned long long next_stack_id{0}; |
| 117 | bool deterministic_id{false}; | 118 | bool deterministic_id{false}; |
| 118 | Pl_MD5* md5_pipeline{nullptr}; | 119 | Pl_MD5* md5_pipeline{nullptr}; |