2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 02:49:00 +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);
void resolveObjectsInStream(int obj_stream_number);
void stopOnError(std::string const& message);
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
QPDFObjGen nextObjGen();
QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
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;
}
}
object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length));
object = {QPDF_Stream::create(this, og, object, stream_offset, length)};
}
void
@ -2101,12 +2101,6 @@ QPDF::newStream(std::string const& data)
return result;
}
QPDFObjectHandle
QPDF::reserveStream(QPDFObjGen const& og)
{
return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
}
std::shared_ptr<QPDFObject>
QPDF::getObjectForParser(int id, int gen, bool parse_pdf)
{
@ -2177,7 +2171,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
void
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");
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* qpdf,
QPDFObjGen const& og,
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length) :
QPDFValue(::ot_stream),
QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) :
QPDFValue(::ot_stream, qpdf, og),
filter_on_write(true),
stream_dict(stream_dict),
length(length)
@ -128,11 +124,7 @@ QPDF_Stream::QPDF_Stream(
std::shared_ptr<QPDFObject>
QPDF_Stream::create(
QPDF* qpdf,
QPDFObjGen const& og,
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length)
QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t 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");
error(
value.getStart(),
"new \"stream\" must have exactly one of \"data\" or "
"\"datafile\"");
"new \"stream\" must have exactly one of \"data\" or \"datafile\"");
} else if (saw_datafile) {
QTC::TC("qpdf", "QPDF_json data and datafile");
error(
value.getStart(),
"existing \"stream\" may at most one of \"data\" or "
"\"datafile\"");
"existing \"stream\" may at most one of \"data\" or \"datafile\"");
} else {
QTC::TC("qpdf", "QPDF_json no stream data in update mode");
}
@ -427,15 +425,15 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
void
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(
replacement.getParsedOffset(),
"the value of an object may not be an indirect object reference");
return;
}
auto& tos = stack.back();
auto og = tos.object.getObjGen();
this->pdf.replaceObject(og, replacement);
pdf.replaceObject(og, replacement);
next_obj = pdf.getObject(og);
setObjectDescription(tos.object, value);
}
@ -575,8 +573,11 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
if (tos.object.isStream()) {
QTC::TC("qpdf", "QPDF_json updating existing stream");
} else {
this->this_stream_needs_data = true;
replaceObject(pdf.reserveStream(tos.object.getObjGen()), value);
this_stream_needs_data = true;
replaceObject(
QPDF_Stream::create(
&pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0),
value);
}
next_obj = tos.object;
} else {

View File

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