Commit 876c238ea9c6b307b95f838a5d34711a57265c07

Authored by m-holger
1 parent 05f8281f

Add a private API version of Pl_Count

... and use it in QPDFWriter and QPDF::generateHintStream.
include/qpdf/QPDFWriter.hh
... ... @@ -597,7 +597,7 @@ class QPDFWriter
597 597 // activate the pipeline stack. When the passed in PipelinePopper goes out of scope, the stack
598 598 // is popped.
599 599 Pipeline* pushPipeline(Pipeline*);
600   - void activatePipelineStack(PipelinePopper&);
  600 + void activatePipelineStack(PipelinePopper& pp, bool discard = false);
601 601 void initializePipelineStack(Pipeline*);
602 602  
603 603 void adjustAESStreamLength(size_t& length);
... ...
libqpdf/QPDFWriter.cc
... ... @@ -6,8 +6,6 @@
6 6  
7 7 #include <qpdf/MD5.hh>
8 8 #include <qpdf/Pl_AES_PDF.hh>
9   -#include <qpdf/Pl_Count.hh>
10   -#include <qpdf/Pl_Discard.hh>
11 9 #include <qpdf/Pl_Flate.hh>
12 10 #include <qpdf/Pl_MD5.hh>
13 11 #include <qpdf/Pl_PNGFilter.hh>
... ... @@ -905,26 +903,26 @@ QPDFWriter::writePad(size_t nspaces)
905 903 Pipeline*
906 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 908 return p;
911 909 }
912 910  
913 911 void
914 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 919 void
922   -QPDFWriter::activatePipelineStack(PipelinePopper& pp)
  920 +QPDFWriter::activatePipelineStack(PipelinePopper& pp, bool discard)
923 921 {
924 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 924 ++m->next_stack_id;
927   - m->pipeline_stack.push_back(c);
  925 + m->pipeline_stack.emplace_back(c);
928 926 m->pipeline = c;
929 927 pp.stack_id = stack_id;
930 928 }
... ... @@ -936,7 +934,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper()
936 934 }
937 935 qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2);
938 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 938 // It might be possible for this assertion to fail if writeLinearized exits by exception when
941 939 // deterministic ID, but I don't think so. As of this writing, this is the only case in which
942 940 // two dynamically allocated PipelinePopper objects ever exist at the same time, so the
... ... @@ -944,7 +942,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper()
944 942 qpdf_assert_debug(qw->m->pipeline->getIdentifier() == stack_id);
945 943 delete qw->m->pipeline_stack.back();
946 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 946 Pipeline* p = qw->m->pipeline_stack.back();
949 947 if (dynamic_cast<Pl_MD5*>(p) == qw->m->md5_pipeline) {
950 948 qw->m->md5_pipeline = nullptr;
... ... @@ -952,7 +950,7 @@ QPDFWriter::PipelinePopper::~PipelinePopper()
952 950 qw->m->pipeline_stack.pop_back();
953 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 956 void
... ... @@ -994,8 +992,7 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper&amp; pp)
994 992 void
995 993 QPDFWriter::pushDiscardFilter(PipelinePopper& pp)
996 994 {
997   - pushPipeline(new Pl_Discard());
998   - activatePipelineStack(pp);
  995 + activatePipelineStack(pp, true);
999 996 }
1000 997  
1001 998 void
... ... @@ -1281,13 +1278,13 @@ QPDFWriter::willFilterStream(
1281 1278  
1282 1279 bool filtered = false;
1283 1280 for (bool first_attempt: {true, false}) {
  1281 + PipelinePopper pp_stream_data(this);
1284 1282 if (stream_data != nullptr) {
1285 1283 pushPipeline(new Pl_String("stream data", nullptr, *stream_data));
  1284 + activatePipelineStack(pp_stream_data);
1286 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 1288 try {
1292 1289 filtered = stream.pipeStreamData(
1293 1290 m->pipeline,
... ... @@ -2678,8 +2675,8 @@ QPDFWriter::writeLinearized()
2678 2675 // Write file in two passes. Part numbers refer to PDF spec 1.4.
2679 2676  
2680 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 2680 for (int pass: {1, 2}) {
2684 2681 if (pass == 1) {
2685 2682 if (!m->lin_pass1_filename.empty()) {
... ... @@ -3011,9 +3008,9 @@ QPDFWriter::registerProgressReporter(std::shared_ptr&lt;ProgressReporter&gt; pr)
3011 3008 void
3012 3009 QPDFWriter::writeStandard()
3013 3010 {
3014   - auto pp_md5 = std::make_shared<PipelinePopper>(this);
  3011 + auto pp_md5 = PipelinePopper(this);
3015 3012 if (m->deterministic_id) {
3016   - pushMD5Pipeline(*pp_md5);
  3013 + pushMD5Pipeline(pp_md5);
3017 3014 }
3018 3015  
3019 3016 // Start writing
... ... @@ -3059,7 +3056,5 @@ QPDFWriter::writeStandard()
3059 3056 "qpdf",
3060 3057 "QPDFWriter standard deterministic ID",
3061 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 5 #include <qpdf/BitStream.hh>
6 6 #include <qpdf/BitWriter.hh>
7 7 #include <qpdf/InputSource_private.hh>
  8 +#include <qpdf/Pipeline_private.hh>
8 9 #include <qpdf/Pl_Buffer.hh>
9   -#include <qpdf/Pl_Count.hh>
10 10 #include <qpdf/Pl_Flate.hh>
11 11 #include <qpdf/Pl_String.hh>
12 12 #include <qpdf/QPDFExc.hh>
... ... @@ -1757,13 +1757,13 @@ QPDF::generateHintStream(
1757 1757 // can get offsets.
1758 1758 Pl_String hint_stream("hint stream", nullptr, hint_buffer);
1759 1759 Pipeline* next = &hint_stream;
1760   - std::shared_ptr<Pipeline> flate;
  1760 + std::unique_ptr<Pipeline> flate;
1761 1761 if (compressed) {
1762 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 1764 next = flate.get();
1765 1765 }
1766   - Pl_Count c("count", next);
  1766 + pl::Count c("count", next);
1767 1767 BitWriter w(&c);
1768 1768  
1769 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 4 #include <qpdf/QPDFWriter.hh>
5 5  
6 6 #include <qpdf/ObjTable.hh>
  7 +#include <qpdf/Pipeline_private.hh>
7 8  
8 9 // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization
9 10 // only.
... ... @@ -98,7 +99,7 @@ class QPDFWriter::Members
98 99 int encryption_dict_objid{0};
99 100 std::string cur_data_key;
100 101 std::list<std::shared_ptr<Pipeline>> to_delete;
101   - Pl_Count* pipeline{nullptr};
  102 + qpdf::pl::Count* pipeline{nullptr};
102 103 std::vector<QPDFObjectHandle> object_queue;
103 104 size_t object_queue_front{0};
104 105 QPDFWriter::ObjTable obj;
... ... @@ -112,7 +113,7 @@ class QPDFWriter::Members
112 113 std::map<QPDFObjGen, int> page_object_to_seq;
113 114 std::map<QPDFObjGen, int> contents_to_page_seq;
114 115 std::map<int, std::vector<QPDFObjGen>> object_stream_to_objects;
115   - std::list<Pipeline*> pipeline_stack;
  116 + std::vector<Pipeline*> pipeline_stack;
116 117 unsigned long long next_stack_id{0};
117 118 bool deterministic_id{false};
118 119 Pl_MD5* md5_pipeline{nullptr};
... ...