2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-03 07:12:28 +00:00

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.
This commit is contained in:
m-holger 2024-09-04 13:10:17 +01:00
parent 7f3b05ddb4
commit 83e0f8da88
5 changed files with 26 additions and 48 deletions

View File

@ -1073,7 +1073,6 @@ class QPDF
QPDFObject* resolve(QPDFObjGen og); QPDFObject* resolve(QPDFObjGen og);
void resolveObjectsInStream(int obj_stream_number); void resolveObjectsInStream(int obj_stream_number);
void stopOnError(std::string const& message); void stopOnError(std::string const& message);
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
QPDFObjGen nextObjGen(); QPDFObjGen nextObjGen();
QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&); QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj); QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);

View File

@ -1547,7 +1547,7 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
throw; throw;
} }
} }
object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length)); object = {QPDF_Stream::create(this, og, object, stream_offset, length)};
} }
void void
@ -2101,12 +2101,6 @@ QPDF::newStream(std::string const& data)
return result; return result;
} }
QPDFObjectHandle
QPDF::reserveStream(QPDFObjGen const& og)
{
return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
}
std::shared_ptr<QPDFObject> std::shared_ptr<QPDFObject>
QPDF::getObjectForParser(int id, int gen, bool parse_pdf) QPDF::getObjectForParser(int id, int gen, bool parse_pdf)
{ {
@ -2177,7 +2171,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
void void
QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
{ {
if (oh.isIndirect() || !oh.isInitialized()) { if (!oh.isInitialized() || (oh.isIndirect() && !(oh.isStream() && oh.getObjGen() == og))) {
QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
throw std::logic_error("QPDF::replaceObject called with indirect object handle"); throw std::logic_error("QPDF::replaceObject called with indirect object handle");
} }

View File

@ -107,12 +107,8 @@ StreamBlobProvider::operator()(Pipeline* p)
} }
QPDF_Stream::QPDF_Stream( QPDF_Stream::QPDF_Stream(
QPDF* qpdf, QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) :
QPDFObjGen const& og, QPDFValue(::ot_stream, qpdf, og),
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length) :
QPDFValue(::ot_stream),
filter_on_write(true), filter_on_write(true),
stream_dict(stream_dict), stream_dict(stream_dict),
length(length) length(length)
@ -128,11 +124,7 @@ QPDF_Stream::QPDF_Stream(
std::shared_ptr<QPDFObject> std::shared_ptr<QPDFObject>
QPDF_Stream::create( QPDF_Stream::create(
QPDF* qpdf, QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length)
QPDFObjGen const& og,
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length)
{ {
return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length)); return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length));
} }

View File

@ -397,14 +397,12 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
QTC::TC("qpdf", "QPDF_json data datafile both or neither"); QTC::TC("qpdf", "QPDF_json data datafile both or neither");
error( error(
value.getStart(), value.getStart(),
"new \"stream\" must have exactly one of \"data\" or " "new \"stream\" must have exactly one of \"data\" or \"datafile\"");
"\"datafile\"");
} else if (saw_datafile) { } else if (saw_datafile) {
QTC::TC("qpdf", "QPDF_json data and datafile"); QTC::TC("qpdf", "QPDF_json data and datafile");
error( error(
value.getStart(), value.getStart(),
"existing \"stream\" may at most one of \"data\" or " "existing \"stream\" may at most one of \"data\" or \"datafile\"");
"\"datafile\"");
} else { } else {
QTC::TC("qpdf", "QPDF_json no stream data in update mode"); QTC::TC("qpdf", "QPDF_json no stream data in update mode");
} }
@ -427,15 +425,15 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
void void
QPDF::JSONReactor::replaceObject(QPDFObjectHandle&& replacement, JSON const& value) QPDF::JSONReactor::replaceObject(QPDFObjectHandle&& replacement, JSON const& value)
{ {
if (replacement.isIndirect()) { auto& tos = stack.back();
auto og = tos.object.getObjGen();
if (replacement.isIndirect() && !(replacement.isStream() && replacement.getObjGen() == og)) {
error( error(
replacement.getParsedOffset(), replacement.getParsedOffset(),
"the value of an object may not be an indirect object reference"); "the value of an object may not be an indirect object reference");
return; return;
} }
auto& tos = stack.back(); pdf.replaceObject(og, replacement);
auto og = tos.object.getObjGen();
this->pdf.replaceObject(og, replacement);
next_obj = pdf.getObject(og); next_obj = pdf.getObject(og);
setObjectDescription(tos.object, value); setObjectDescription(tos.object, value);
} }
@ -575,8 +573,11 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
if (tos.object.isStream()) { if (tos.object.isStream()) {
QTC::TC("qpdf", "QPDF_json updating existing stream"); QTC::TC("qpdf", "QPDF_json updating existing stream");
} else { } else {
this->this_stream_needs_data = true; this_stream_needs_data = true;
replaceObject(pdf.reserveStream(tos.object.getObjGen()), value); replaceObject(
QPDF_Stream::create(
&pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0),
value);
} }
next_obj = tos.object; next_obj = tos.object;
} else { } else {

View File

@ -13,22 +13,18 @@
class Pipeline; class Pipeline;
class QPDF; class QPDF;
class QPDF_Stream: public QPDFValue class QPDF_Stream final: public QPDFValue
{ {
public: public:
~QPDF_Stream() override = default; ~QPDF_Stream() final = default;
static std::shared_ptr<QPDFObject> create( static std::shared_ptr<QPDFObject>
QPDF*, create(QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
QPDFObjGen const& og, std::shared_ptr<QPDFObject> copy(bool shallow = false) final;
QPDFObjectHandle stream_dict, std::string unparse() final;
qpdf_offset_t offset, void writeJSON(int json_version, JSON::Writer& p) final;
size_t length);
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
std::string unparse() override;
void writeJSON(int json_version, JSON::Writer& p) override;
void setDescription( void setDescription(
QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) override; QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) final;
void disconnect() override; void disconnect() final;
QPDFObjectHandle getDict() const; QPDFObjectHandle getDict() const;
bool isDataModified() const; bool isDataModified() const;
void setFilterOnWrite(bool); void setFilterOnWrite(bool);
@ -80,11 +76,7 @@ class QPDF_Stream: public QPDFValue
private: private:
QPDF_Stream( QPDF_Stream(
QPDF*, QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
QPDFObjGen const& og,
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length);
static std::map<std::string, std::string> filter_abbreviations; static std::map<std::string, std::string> filter_abbreviations;
static std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>> static std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>>
filter_factories; filter_factories;