Commit 83e0f8da885379f0cf9612c51237f3350f052eb0

Authored by m-holger
1 parent 7f3b05dd

Tidy QPDF_Stream

1. Make class final
2. Pass og parameter by value
3. Properly initialize qpdf and og

Also, tweak QPDF::replaceObject to allow stream replacement without
violating the requirement that streams must always be indirect objects.

Also, remove QPDF::reserveStream as it does not do what the name implies
and having this as a separate methods does not aid code readability.
include/qpdf/QPDF.hh
@@ -1073,7 +1073,6 @@ class QPDF @@ -1073,7 +1073,6 @@ class QPDF
1073 QPDFObject* resolve(QPDFObjGen og); 1073 QPDFObject* resolve(QPDFObjGen og);
1074 void resolveObjectsInStream(int obj_stream_number); 1074 void resolveObjectsInStream(int obj_stream_number);
1075 void stopOnError(std::string const& message); 1075 void stopOnError(std::string const& message);
1076 - QPDFObjectHandle reserveStream(QPDFObjGen const& og);  
1077 QPDFObjGen nextObjGen(); 1076 QPDFObjGen nextObjGen();
1078 QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&); 1077 QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
1079 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj); 1078 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
libqpdf/QPDF.cc
@@ -1547,7 +1547,7 @@ QPDF::readStream(QPDFObjectHandle&amp; object, QPDFObjGen og, qpdf_offset_t offset) @@ -1547,7 +1547,7 @@ QPDF::readStream(QPDFObjectHandle&amp; object, QPDFObjGen og, qpdf_offset_t offset)
1547 throw; 1547 throw;
1548 } 1548 }
1549 } 1549 }
1550 - object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length)); 1550 + object = {QPDF_Stream::create(this, og, object, stream_offset, length)};
1551 } 1551 }
1552 1552
1553 void 1553 void
@@ -2101,12 +2101,6 @@ QPDF::newStream(std::string const&amp; data) @@ -2101,12 +2101,6 @@ QPDF::newStream(std::string const&amp; data)
2101 return result; 2101 return result;
2102 } 2102 }
2103 2103
2104 -QPDFObjectHandle  
2105 -QPDF::reserveStream(QPDFObjGen const& og)  
2106 -{  
2107 - return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};  
2108 -}  
2109 -  
2110 std::shared_ptr<QPDFObject> 2104 std::shared_ptr<QPDFObject>
2111 QPDF::getObjectForParser(int id, int gen, bool parse_pdf) 2105 QPDF::getObjectForParser(int id, int gen, bool parse_pdf)
2112 { 2106 {
@@ -2177,7 +2171,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) @@ -2177,7 +2171,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
2177 void 2171 void
2178 QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) 2172 QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
2179 { 2173 {
2180 - if (oh.isIndirect() || !oh.isInitialized()) { 2174 + if (!oh.isInitialized() || (oh.isIndirect() && !(oh.isStream() && oh.getObjGen() == og))) {
2181 QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); 2175 QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
2182 throw std::logic_error("QPDF::replaceObject called with indirect object handle"); 2176 throw std::logic_error("QPDF::replaceObject called with indirect object handle");
2183 } 2177 }
libqpdf/QPDF_Stream.cc
@@ -107,12 +107,8 @@ StreamBlobProvider::operator()(Pipeline* p) @@ -107,12 +107,8 @@ StreamBlobProvider::operator()(Pipeline* p)
107 } 107 }
108 108
109 QPDF_Stream::QPDF_Stream( 109 QPDF_Stream::QPDF_Stream(
110 - QPDF* qpdf,  
111 - QPDFObjGen const& og,  
112 - QPDFObjectHandle stream_dict,  
113 - qpdf_offset_t offset,  
114 - size_t length) :  
115 - QPDFValue(::ot_stream), 110 + QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) :
  111 + QPDFValue(::ot_stream, qpdf, og),
116 filter_on_write(true), 112 filter_on_write(true),
117 stream_dict(stream_dict), 113 stream_dict(stream_dict),
118 length(length) 114 length(length)
@@ -128,11 +124,7 @@ QPDF_Stream::QPDF_Stream( @@ -128,11 +124,7 @@ QPDF_Stream::QPDF_Stream(
128 124
129 std::shared_ptr<QPDFObject> 125 std::shared_ptr<QPDFObject>
130 QPDF_Stream::create( 126 QPDF_Stream::create(
131 - QPDF* qpdf,  
132 - QPDFObjGen const& og,  
133 - QPDFObjectHandle stream_dict,  
134 - qpdf_offset_t offset,  
135 - size_t length) 127 + QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length)
136 { 128 {
137 return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length)); 129 return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length));
138 } 130 }
libqpdf/QPDF_json.cc
@@ -397,14 +397,12 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value) @@ -397,14 +397,12 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value)
397 QTC::TC("qpdf", "QPDF_json data datafile both or neither"); 397 QTC::TC("qpdf", "QPDF_json data datafile both or neither");
398 error( 398 error(
399 value.getStart(), 399 value.getStart(),
400 - "new \"stream\" must have exactly one of \"data\" or "  
401 - "\"datafile\""); 400 + "new \"stream\" must have exactly one of \"data\" or \"datafile\"");
402 } else if (saw_datafile) { 401 } else if (saw_datafile) {
403 QTC::TC("qpdf", "QPDF_json data and datafile"); 402 QTC::TC("qpdf", "QPDF_json data and datafile");
404 error( 403 error(
405 value.getStart(), 404 value.getStart(),
406 - "existing \"stream\" may at most one of \"data\" or "  
407 - "\"datafile\""); 405 + "existing \"stream\" may at most one of \"data\" or \"datafile\"");
408 } else { 406 } else {
409 QTC::TC("qpdf", "QPDF_json no stream data in update mode"); 407 QTC::TC("qpdf", "QPDF_json no stream data in update mode");
410 } 408 }
@@ -427,15 +425,15 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value) @@ -427,15 +425,15 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value)
427 void 425 void
428 QPDF::JSONReactor::replaceObject(QPDFObjectHandle&& replacement, JSON const& value) 426 QPDF::JSONReactor::replaceObject(QPDFObjectHandle&& replacement, JSON const& value)
429 { 427 {
430 - if (replacement.isIndirect()) { 428 + auto& tos = stack.back();
  429 + auto og = tos.object.getObjGen();
  430 + if (replacement.isIndirect() && !(replacement.isStream() && replacement.getObjGen() == og)) {
431 error( 431 error(
432 replacement.getParsedOffset(), 432 replacement.getParsedOffset(),
433 "the value of an object may not be an indirect object reference"); 433 "the value of an object may not be an indirect object reference");
434 return; 434 return;
435 } 435 }
436 - auto& tos = stack.back();  
437 - auto og = tos.object.getObjGen();  
438 - this->pdf.replaceObject(og, replacement); 436 + pdf.replaceObject(og, replacement);
439 next_obj = pdf.getObject(og); 437 next_obj = pdf.getObject(og);
440 setObjectDescription(tos.object, value); 438 setObjectDescription(tos.object, value);
441 } 439 }
@@ -575,8 +573,11 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -575,8 +573,11 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
575 if (tos.object.isStream()) { 573 if (tos.object.isStream()) {
576 QTC::TC("qpdf", "QPDF_json updating existing stream"); 574 QTC::TC("qpdf", "QPDF_json updating existing stream");
577 } else { 575 } else {
578 - this->this_stream_needs_data = true;  
579 - replaceObject(pdf.reserveStream(tos.object.getObjGen()), value); 576 + this_stream_needs_data = true;
  577 + replaceObject(
  578 + QPDF_Stream::create(
  579 + &pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0),
  580 + value);
580 } 581 }
581 next_obj = tos.object; 582 next_obj = tos.object;
582 } else { 583 } else {
libqpdf/qpdf/QPDF_Stream.hh
@@ -13,22 +13,18 @@ @@ -13,22 +13,18 @@
13 class Pipeline; 13 class Pipeline;
14 class QPDF; 14 class QPDF;
15 15
16 -class QPDF_Stream: public QPDFValue 16 +class QPDF_Stream final: public QPDFValue
17 { 17 {
18 public: 18 public:
19 - ~QPDF_Stream() override = default;  
20 - static std::shared_ptr<QPDFObject> create(  
21 - QPDF*,  
22 - QPDFObjGen const& og,  
23 - QPDFObjectHandle stream_dict,  
24 - qpdf_offset_t offset,  
25 - size_t length);  
26 - std::shared_ptr<QPDFObject> copy(bool shallow = false) override;  
27 - std::string unparse() override;  
28 - void writeJSON(int json_version, JSON::Writer& p) override; 19 + ~QPDF_Stream() final = default;
  20 + static std::shared_ptr<QPDFObject>
  21 + create(QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
  22 + std::shared_ptr<QPDFObject> copy(bool shallow = false) final;
  23 + std::string unparse() final;
  24 + void writeJSON(int json_version, JSON::Writer& p) final;
29 void setDescription( 25 void setDescription(
30 - QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) override;  
31 - void disconnect() override; 26 + QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) final;
  27 + void disconnect() final;
32 QPDFObjectHandle getDict() const; 28 QPDFObjectHandle getDict() const;
33 bool isDataModified() const; 29 bool isDataModified() const;
34 void setFilterOnWrite(bool); 30 void setFilterOnWrite(bool);
@@ -80,11 +76,7 @@ class QPDF_Stream: public QPDFValue @@ -80,11 +76,7 @@ class QPDF_Stream: public QPDFValue
80 76
81 private: 77 private:
82 QPDF_Stream( 78 QPDF_Stream(
83 - QPDF*,  
84 - QPDFObjGen const& og,  
85 - QPDFObjectHandle stream_dict,  
86 - qpdf_offset_t offset,  
87 - size_t length); 79 + QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
88 static std::map<std::string, std::string> filter_abbreviations; 80 static std::map<std::string, std::string> filter_abbreviations;
89 static std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>> 81 static std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>>
90 filter_factories; 82 filter_factories;