From 8a217eb3a26931453b4f003c6c18ad8569230cf1 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 8 Jul 2012 14:19:19 -0400 Subject: Add concept of reserved objects QPDFObjectHandle::{new,is,assert}Reserved, QPDF::replaceReserved provide a mechanism to add objects to a PDF file when there are circular references. This is a prerequisite to copying objects from one PDF to another. --- libqpdf/QPDFObjectHandle.cc | 62 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 73d0019c..25298bee 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,7 +21,8 @@ QPDFObjectHandle::QPDFObjectHandle() : initialized(false), objid(0), - generation(0) + generation(0), + reserved(false) { } @@ -28,7 +30,8 @@ QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, int objid, int generation) : initialized(true), qpdf(qpdf), objid(objid), - generation(generation) + generation(generation), + reserved(false) { } @@ -37,7 +40,8 @@ QPDFObjectHandle::QPDFObjectHandle(QPDFObject* data) : qpdf(0), objid(0), generation(0), - obj(data) + obj(data), + reserved(false) { } @@ -165,6 +169,14 @@ QPDFObjectHandle::isStream() return QPDFObjectTypeAccessor::check(obj.getPointer()); } +bool +QPDFObjectHandle::isReserved() +{ + // dereference will clear reserved if this has been replaced + dereference(); + return this->reserved; +} + bool QPDFObjectHandle::isIndirect() { @@ -568,6 +580,11 @@ QPDFObjectHandle::unparse() std::string QPDFObjectHandle::unparseResolved() { + if (this->reserved) + { + throw std::logic_error( + "QPDFObjectHandle: attempting to unparse a reserved object"); + } dereference(); return this->obj->unparse(); } @@ -689,6 +706,19 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) return QPDFObjectHandle::newStream(qpdf, b); } +QPDFObjectHandle +QPDFObjectHandle::newReserved(QPDF* qpdf) +{ + // Reserve a spot for this object by assigning it an object + // number, but then return an unresolved handle to the object. + QPDFObjectHandle reserved = qpdf->makeIndirectObject( + QPDFObjectHandle(new QPDF_Reserved())); + QPDFObjectHandle result = + newIndirect(qpdf, reserved.objid, reserved.generation); + result.reserved = true; + return result; +} + QPDFObjectHandle QPDFObjectHandle::shallowCopy() { @@ -746,6 +776,13 @@ QPDFObjectHandle::makeDirectInternal(std::set& visited) visited.insert(cur_objid); } + if (isReserved()) + { + throw std::logic_error( + "QPDFObjectHandle: attempting to make a" + " reserved object handle direct"); + } + dereference(); this->objid = 0; this->generation = 0; @@ -902,6 +939,12 @@ QPDFObjectHandle::assertStream() assertType("Stream", isStream()); } +void +QPDFObjectHandle::assertReserved() +{ + assertType("Reserved", isReserved()); +} + void QPDFObjectHandle::assertScalar() { @@ -929,12 +972,21 @@ QPDFObjectHandle::dereference() { if (this->obj.getPointer() == 0) { - this->obj = QPDF::Resolver::resolve( + PointerHolder obj = QPDF::Resolver::resolve( this->qpdf, this->objid, this->generation); - if (this->obj.getPointer() == 0) + if (obj.getPointer() == 0) { QTC::TC("qpdf", "QPDFObjectHandle indirect to unknown"); this->obj = new QPDF_Null(); } + else if (dynamic_cast(obj.getPointer())) + { + // Do not resolve + } + else + { + this->reserved = false; + this->obj = obj; + } } } -- cgit v1.2.3-70-g09d2