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,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&amp; pp) @@ -994,8 +992,7 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper&amp; 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&lt;ProgressReporter&gt; pr) @@ -3011,9 +3008,9 @@ QPDFWriter::registerProgressReporter(std::shared_ptr&lt;ProgressReporter&gt; 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};