Commit 83e0f8da885379f0cf9612c51237f3350f052eb0
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.
Showing
5 changed files
with
26 additions
and
48 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -1073,7 +1073,6 @@ class QPDF |
| 1073 | 1073 | QPDFObject* resolve(QPDFObjGen og); |
| 1074 | 1074 | void resolveObjectsInStream(int obj_stream_number); |
| 1075 | 1075 | void stopOnError(std::string const& message); |
| 1076 | - QPDFObjectHandle reserveStream(QPDFObjGen const& og); | |
| 1077 | 1076 | QPDFObjGen nextObjGen(); |
| 1078 | 1077 | QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&); |
| 1079 | 1078 | QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -1547,7 +1547,7 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset) |
| 1547 | 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 | 1553 | void |
| ... | ... | @@ -2101,12 +2101,6 @@ QPDF::newStream(std::string const& data) |
| 2101 | 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 | 2104 | std::shared_ptr<QPDFObject> |
| 2111 | 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 | 2171 | void |
| 2178 | 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 | 2175 | QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); |
| 2182 | 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 | 107 | } |
| 108 | 108 | |
| 109 | 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 | 112 | filter_on_write(true), |
| 117 | 113 | stream_dict(stream_dict), |
| 118 | 114 | length(length) |
| ... | ... | @@ -128,11 +124,7 @@ QPDF_Stream::QPDF_Stream( |
| 128 | 124 | |
| 129 | 125 | std::shared_ptr<QPDFObject> |
| 130 | 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 | 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& value) |
| 397 | 397 | QTC::TC("qpdf", "QPDF_json data datafile both or neither"); |
| 398 | 398 | error( |
| 399 | 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 | 401 | } else if (saw_datafile) { |
| 403 | 402 | QTC::TC("qpdf", "QPDF_json data and datafile"); |
| 404 | 403 | error( |
| 405 | 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 | 406 | } else { |
| 409 | 407 | QTC::TC("qpdf", "QPDF_json no stream data in update mode"); |
| 410 | 408 | } |
| ... | ... | @@ -427,15 +425,15 @@ QPDF::JSONReactor::containerEnd(JSON const& value) |
| 427 | 425 | void |
| 428 | 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 | 431 | error( |
| 432 | 432 | replacement.getParsedOffset(), |
| 433 | 433 | "the value of an object may not be an indirect object reference"); |
| 434 | 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 | 437 | next_obj = pdf.getObject(og); |
| 440 | 438 | setObjectDescription(tos.object, value); |
| 441 | 439 | } |
| ... | ... | @@ -575,8 +573,11 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) |
| 575 | 573 | if (tos.object.isStream()) { |
| 576 | 574 | QTC::TC("qpdf", "QPDF_json updating existing stream"); |
| 577 | 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 | 582 | next_obj = tos.object; |
| 582 | 583 | } else { | ... | ... |
libqpdf/qpdf/QPDF_Stream.hh
| ... | ... | @@ -13,22 +13,18 @@ |
| 13 | 13 | class Pipeline; |
| 14 | 14 | class QPDF; |
| 15 | 15 | |
| 16 | -class QPDF_Stream: public QPDFValue | |
| 16 | +class QPDF_Stream final: public QPDFValue | |
| 17 | 17 | { |
| 18 | 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 | 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 | 28 | QPDFObjectHandle getDict() const; |
| 33 | 29 | bool isDataModified() const; |
| 34 | 30 | void setFilterOnWrite(bool); |
| ... | ... | @@ -80,11 +76,7 @@ class QPDF_Stream: public QPDFValue |
| 80 | 76 | |
| 81 | 77 | private: |
| 82 | 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 | 80 | static std::map<std::string, std::string> filter_abbreviations; |
| 89 | 81 | static std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>> |
| 90 | 82 | filter_factories; | ... | ... |