diff options
author | Jay Berkenbilt <jberkenbilt@users.noreply.github.com> | 2022-09-01 19:14:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-01 19:14:56 +0200 |
commit | f8fd7d60e301b9b1bf4d705ce747e281c320487e (patch) | |
tree | 4aba6da08ae9d441ecf57eabefdc76185137d28d /libqpdf | |
parent | a078202c1b5823f1c13a4c559619158054029e73 (diff) | |
parent | 805c1ad47968e33e1296af9a31492f6916ad9113 (diff) | |
download | qpdf-f8fd7d60e301b9b1bf4d705ce747e281c320487e.tar.zst |
Merge pull request #726 from m-holger/tidy3
Split QPDFObject into QPDFObject and QPDFValue
Diffstat (limited to 'libqpdf')
33 files changed, 482 insertions, 572 deletions
diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt index 51f7476d..686ea04a 100644 --- a/libqpdf/CMakeLists.txt +++ b/libqpdf/CMakeLists.txt @@ -85,6 +85,7 @@ set(libqpdf_SOURCES QPDFSystemError.cc QPDFTokenizer.cc QPDFUsage.cc + QPDFValue.cc QPDFWriter.cc QPDFXRefEntry.cc QPDF_Array.cc @@ -99,6 +100,7 @@ set(libqpdf_SOURCES QPDF_Reserved.cc QPDF_Stream.cc QPDF_String.cc + QPDF_Unresolved.cc QPDF_encryption.cc QPDF_json.cc QPDF_linearization.cc diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 6ae74b25..9593c44f 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -24,7 +24,9 @@ #include <qpdf/QPDF_Array.hh> #include <qpdf/QPDF_Dictionary.hh> #include <qpdf/QPDF_Null.hh> +#include <qpdf/QPDF_Reserved.hh> #include <qpdf/QPDF_Stream.hh> +#include <qpdf/QPDF_Unresolved.hh> #include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> @@ -222,7 +224,6 @@ QPDF::Members::Members() : immediate_copy_from(false), in_parse(false), parsed(false), - ever_replaced_objects(false), first_xref_item_offset(0), uncompressed_after_compressed(false) { @@ -258,6 +259,7 @@ QPDF::~QPDF() this->m->xref_table.clear(); for (auto const& iter: this->m->obj_cache) { QPDFObject::ObjAccessor::releaseResolved(iter.second.object.get()); + iter.second.object->resetObjGen(); } } @@ -1397,7 +1399,7 @@ QPDF::fixDanglingReferences(bool force) std::list<QPDFObjectHandle> queue; queue.push_back(this->m->trailer); for (auto const& og: to_process) { - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og); + auto obj = getObject(og); if (obj.isDictionary() || obj.isArray()) { queue.push_back(obj); } else if (obj.isStream()) { @@ -1419,18 +1421,15 @@ QPDF::fixDanglingReferences(bool force) to_check.push_back(iter.second); } } else if (obj.isArray()) { - QPDF_Array* arr = dynamic_cast<QPDF_Array*>( - QPDFObjectHandle::ObjAccessor::getObject(obj).get()); + auto arr = QPDFObjectHandle::ObjAccessor::asArray(obj); arr->addExplicitElementsToList(to_check); } for (auto sub: to_check) { if (sub.isIndirect()) { - if (sub.getOwningQPDF() == this) { - QPDFObjGen og(sub.getObjGen()); - if (this->m->obj_cache.count(og) == 0) { - QTC::TC("qpdf", "QPDF detected dangling ref"); - queue.push_back(sub); - } + if ((sub.getOwningQPDF() == this) && + isUnresolved(sub.getObjGen())) { + QTC::TC("qpdf", "QPDF detected dangling ref"); + queue.push_back(sub); } } else { queue.push_back(sub); @@ -1462,8 +1461,7 @@ QPDF::getAllObjects() fixDanglingReferences(true); std::vector<QPDFObjectHandle> result; for (auto const& iter: this->m->obj_cache) { - QPDFObjGen const& og = iter.first; - result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og)); + result.push_back(newIndirect(iter.first, iter.second.object)); } return result; } @@ -1888,7 +1886,7 @@ QPDF::readObjectAtOffset( "expected endobj"); } - if (!this->m->obj_cache.count(og)) { + if (isUnresolved(og)) { // Store the object in the cache here so it gets cached // whether we first know the offset or whether we first know // the object ID and generation (in which we case we would get @@ -1919,8 +1917,8 @@ QPDF::readObjectAtOffset( } } qpdf_offset_t end_after_space = this->m->file->tell(); - - this->m->obj_cache[og] = ObjCache( + updateCache( + og, QPDFObjectHandle::ObjAccessor::getObject(oh), end_before_space, end_after_space); @@ -1929,31 +1927,14 @@ QPDF::readObjectAtOffset( return oh; } -bool -QPDF::objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph) -{ - // See if the object cached at og, if any, is the one passed in. - // QPDFObjectHandle uses this to detect outdated handles to - // replaced or swapped objects. This is a somewhat expensive check - // because it happens with every dereference of a - // QPDFObjectHandle. To reduce the hit somewhat, short-circuit the - // check if we never called a function that replaces an object - // already in cache. It is important for functions that do this to - // set ever_replaced_objects = true. - - if (!this->m->ever_replaced_objects) { - return false; - } - auto c = this->m->obj_cache.find(og); - if (c == this->m->obj_cache.end()) { - return true; - } - return (c->second.object.get() != oph.get()); -} - -std::shared_ptr<QPDFObject> +void QPDF::resolve(QPDFObjGen const& og) { + if (isCached(og) && !isUnresolved(og)) { + // We only need to resolve unresolved objects + return; + } + // Check object cache before checking xref table. This allows us // to insert things into the object cache that don't actually // exist in the file. @@ -1967,11 +1948,12 @@ QPDF::resolve(QPDFObjGen const& og) "", this->m->file->getLastOffset(), ("loop detected resolving object " + og.unparse(' '))); - return QPDF_Null::create(); + updateCache(og, QPDF_Null::create(), -1, -1); + return; } ResolveRecorder rr(this, og); - if ((!this->m->obj_cache.count(og)) && this->m->xref_table.count(og)) { + if (m->xref_table.count(og) != 0) { QPDFXRefEntry const& entry = this->m->xref_table[og]; try { switch (entry.getType()) { @@ -2009,19 +1991,17 @@ QPDF::resolve(QPDFObjGen const& og) ": error reading object: " + e.what())); } } - if (this->m->obj_cache.count(og) == 0) { + + if (isUnresolved(og)) { // PDF spec says unknown objects resolve to the null object. QTC::TC("qpdf", "QPDF resolve failure to null"); - QPDFObjectHandle oh = QPDFObjectHandle::newNull(); - this->m->obj_cache[og] = - ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); + updateCache(og, QPDF_Null::create(), -1, -1); } - std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object); + auto result(this->m->obj_cache[og].object); if (!result->hasDescription()) { result->setDescription(this, ("object " + og.unparse(' '))); } - return result; } void @@ -2109,15 +2089,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number) // objects appended to the file, so it is necessary to recheck the // xref table and only cache what would actually be resolved here. for (auto const& iter: offsets) { - int obj = iter.first; - QPDFObjGen og(obj, 0); + QPDFObjGen og(iter.first, 0); QPDFXRefEntry const& entry = this->m->xref_table[og]; if ((entry.getType() == 2) && (entry.getObjStreamNumber() == obj_stream_number)) { int offset = iter.second; input->seek(offset, SEEK_SET); QPDFObjectHandle oh = readObject(input, "", og, true); - this->m->obj_cache[og] = ObjCache( + updateCache( + og, QPDFObjectHandle::ObjAccessor::getObject(oh), end_before_space, end_after_space); @@ -2128,6 +2108,47 @@ QPDF::resolveObjectsInStream(int obj_stream_number) } QPDFObjectHandle +QPDF::newIndirect(QPDFObjGen const& og, std::shared_ptr<QPDFObject> const& obj) +{ + obj->setObjGen(this, og); + if (!obj->hasDescription()) { + obj->setDescription(this, "object " + og.unparse(' ')); + } + return QPDFObjectHandle::Factory::newIndirect(obj); +} + +void +QPDF::updateCache( + QPDFObjGen const& og, + std::shared_ptr<QPDFObject> const& object, + qpdf_offset_t end_before_space, + qpdf_offset_t end_after_space) +{ + object->setObjGen(this, og); + if (isCached(og)) { + auto& cache = m->obj_cache[og]; + cache.object->resetObjGen(); + cache.object->assign(object); + cache.end_before_space = end_before_space; + cache.end_after_space = end_after_space; + } else { + m->obj_cache[og] = ObjCache(object, end_before_space, end_after_space); + } +} + +bool +QPDF::isCached(QPDFObjGen const& og) +{ + return m->obj_cache.count(og) != 0; +} + +bool +QPDF::isUnresolved(QPDFObjGen const& og) +{ + return !isCached(og) || m->obj_cache[og].object->isUnresolved(); +} + +QPDFObjectHandle QPDF::makeIndirectObject(QPDFObjectHandle oh) { int max_objid = toI(getObjectCount()); @@ -2136,19 +2157,21 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) "max object id is too high to create new objects"); } QPDFObjGen next(max_objid + 1, 0); - this->m->obj_cache[next] = + m->obj_cache[next] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); - return QPDFObjectHandle::Factory::newIndirect(this, next); + return newIndirect(next, m->obj_cache[next].object); } QPDFObjectHandle QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) { - if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) { + if (!isCached(og) && !m->xref_table.count(og)) { resolve(og); - replaceObject(og, QPDFObjectHandle::Factory::makeReserved()); + m->obj_cache[og].object = QPDF_Reserved::create(); + return newIndirect(og, m->obj_cache[og].object); + } else { + return getObject(og); } - return getObject(og); } QPDFObjectHandle @@ -2161,7 +2184,13 @@ QPDF::reserveStream(QPDFObjGen const& og) QPDFObjectHandle QPDF::getObject(QPDFObjGen const& og) { - return QPDFObjectHandle::Factory::newIndirect(this, og); + if (!og.isIndirect()) { + return QPDFObjectHandle::newNull(); + } + if (!isCached(og)) { + m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(this, og), -1, -1); + } + return newIndirect(og, m->obj_cache[og].object); } QPDFObjectHandle @@ -2196,14 +2225,11 @@ QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) throw std::logic_error( "QPDF::replaceObject called with indirect object handle"); } - // Force new object to appear in the cache resolve(og); // Replace the object in the object cache - this->m->ever_replaced_objects = true; - this->m->obj_cache[og] = - ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); + updateCache(og, QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); } void @@ -2456,12 +2482,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) QPDFObjGen local_og(result.getObjGen()); // Copy information from the foreign stream so we can pipe its // data later without keeping the original QPDF object around. + QPDF* foreign_stream_qpdf = foreign.getOwningQPDF( false, "unable to retrieve owning qpdf from foreign stream"); - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>( - QPDFObjectHandle::ObjAccessor::getObject(foreign).get()); - if (!stream) { + auto stream = QPDFObjectHandle::ObjAccessor::asStream(foreign); + if (stream == nullptr) { throw std::logic_error("unable to retrieve underlying" " stream object from foreign stream"); } @@ -2525,10 +2551,7 @@ QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) // cache. resolve(og1); resolve(og2); - ObjCache t = this->m->obj_cache[og1]; - this->m->ever_replaced_objects = true; - this->m->obj_cache[og1] = this->m->obj_cache[og2]; - this->m->obj_cache[og2] = t; + m->obj_cache[og1].object->swapWith(m->obj_cache[og2].object); } unsigned long long diff --git a/libqpdf/QPDFObject.cc b/libqpdf/QPDFObject.cc index 382dd6c6..8b538021 100644 --- a/libqpdf/QPDFObject.cc +++ b/libqpdf/QPDFObject.cc @@ -1,47 +1,10 @@ #include <qpdf/QPDFObject.hh> -QPDFObject::QPDFObject() : - owning_qpdf(nullptr), - parsed_offset(-1) -{ -} - -std::shared_ptr<QPDFObject> -QPDFObject::do_create(QPDFObject* object) -{ - std::shared_ptr<QPDFObject> obj(object); - return obj; -} - -void -QPDFObject::setDescription(QPDF* qpdf, std::string const& description) -{ - this->owning_qpdf = qpdf; - this->object_description = description; -} - -bool -QPDFObject::getDescription(QPDF*& qpdf, std::string& description) -{ - qpdf = this->owning_qpdf; - description = this->object_description; - return this->owning_qpdf != nullptr; -} - -bool -QPDFObject::hasDescription() -{ - return this->owning_qpdf != nullptr; -} +#include <qpdf/QPDF.hh> void -QPDFObject::setParsedOffset(qpdf_offset_t offset) -{ - this->parsed_offset = offset; -} - -qpdf_offset_t -QPDFObject::getParsedOffset() +QPDFObject::doResolve() { - return this->parsed_offset; + auto og = value->og; + QPDF::Resolver::resolve(value->qpdf, og); } diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 2227a77b..19a85034 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -21,6 +21,7 @@ #include <qpdf/QPDF_Reserved.hh> #include <qpdf/QPDF_Stream.hh> #include <qpdf/QPDF_String.hh> +#include <qpdf/QPDF_Unresolved.hh> #include <qpdf/SparseOHArray.hh> #include <qpdf/QIntC.hh> @@ -234,29 +235,6 @@ LastChar::getLastChar() return this->last_char; } -QPDFObjectHandle::QPDFObjectHandle() : - initialized(false), - qpdf(nullptr), - reserved(false) -{ -} - -QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, QPDFObjGen const& og) : - initialized(true), - qpdf(qpdf), - og(og), - reserved(false) -{ -} - -QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) : - initialized(true), - qpdf(nullptr), - obj(data), - reserved(false) -{ -} - void QPDFObjectHandle::releaseResolved() { @@ -286,24 +264,90 @@ QPDFObjectHandle::getTypeName() return dereference() ? this->obj->getTypeName() : "uninitialized"; } -namespace +QPDF_Array* +QPDFObjectHandle::asArray() { - template <class T> - class QPDFObjectTypeAccessor - { - public: - static bool - check(std::shared_ptr<QPDFObject> const& o) - { - return (o && dynamic_cast<T const*>(o.get())); - } - }; -} // namespace + return dereference() ? obj->as<QPDF_Array>() : nullptr; +} + +QPDF_Bool* +QPDFObjectHandle::asBool() +{ + return dereference() ? obj->as<QPDF_Bool>() : nullptr; +} + +QPDF_Dictionary* +QPDFObjectHandle::asDictionary() +{ + return dereference() ? obj->as<QPDF_Dictionary>() : nullptr; +} + +QPDF_InlineImage* +QPDFObjectHandle::asInlineImage() +{ + return dereference() ? obj->as<QPDF_InlineImage>() : nullptr; +} + +QPDF_Integer* +QPDFObjectHandle::asInteger() +{ + return dereference() ? obj->as<QPDF_Integer>() : nullptr; +} + +QPDF_Name* +QPDFObjectHandle::asName() +{ + return dereference() ? obj->as<QPDF_Name>() : nullptr; +} + +QPDF_Null* +QPDFObjectHandle::asNull() +{ + return dereference() ? obj->as<QPDF_Null>() : nullptr; +} + +QPDF_Operator* +QPDFObjectHandle::asOperator() +{ + return dereference() ? obj->as<QPDF_Operator>() : nullptr; +} + +QPDF_Real* +QPDFObjectHandle::asReal() +{ + return dereference() ? obj->as<QPDF_Real>() : nullptr; +} + +QPDF_Reserved* +QPDFObjectHandle::asReserved() +{ + return dereference() ? obj->as<QPDF_Reserved>() : nullptr; +} + +QPDF_Stream* +QPDFObjectHandle::asStream() +{ + return dereference() ? obj->as<QPDF_Stream>() : nullptr; +} + +QPDF_Stream* +QPDFObjectHandle::asStreamWithAssert() +{ + auto stream = asStream(); + assertType("stream", stream); + return stream; +} + +QPDF_String* +QPDFObjectHandle::asString() +{ + return dereference() ? obj->as<QPDF_String>() : nullptr; +} bool QPDFObjectHandle::isBool() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Bool>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_boolean); } bool @@ -312,26 +356,26 @@ QPDFObjectHandle::isDirectNull() const // Don't call dereference() -- this is a const method, and we know // objid == 0, so there's nothing to resolve. return ( - this->initialized && (getObjectID() == 0) && - QPDFObjectTypeAccessor<QPDF_Null>::check(obj)); + isInitialized() && (getObjectID() == 0) && + (obj->getTypeCode() == QPDFObject::ot_null)); } bool QPDFObjectHandle::isNull() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Null>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_null); } bool QPDFObjectHandle::isInteger() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Integer>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_integer); } bool QPDFObjectHandle::isReal() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Real>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_real); } bool @@ -368,51 +412,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) bool QPDFObjectHandle::isName() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Name>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_name); } bool QPDFObjectHandle::isString() { - return dereference() && QPDFObjectTypeAccessor<QPDF_String>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_string); } bool QPDFObjectHandle::isOperator() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Operator>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_operator); } bool QPDFObjectHandle::isInlineImage() { - return dereference() && - QPDFObjectTypeAccessor<QPDF_InlineImage>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_inlineimage); } bool QPDFObjectHandle::isArray() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Array>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_array); } bool QPDFObjectHandle::isDictionary() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_dictionary); } bool QPDFObjectHandle::isStream() { - return dereference() && QPDFObjectTypeAccessor<QPDF_Stream>::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_stream); } bool QPDFObjectHandle::isReserved() { - // dereference will clear reserved if this has been replaced - return dereference() && this->reserved; + return dereference() && (obj->getTypeCode() == QPDFObject::ot_reserved); } bool @@ -450,8 +492,9 @@ QPDFObjectHandle::isStreamOfType( bool QPDFObjectHandle::getBoolValue() { - if (isBool()) { - return dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); + auto boolean = asBool(); + if (boolean) { + return boolean->getVal(); } else { typeWarning("boolean", "returning false"); QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); @@ -462,10 +505,11 @@ QPDFObjectHandle::getBoolValue() bool QPDFObjectHandle::getValueAsBool(bool& value) { - if (!isBool()) { + auto boolean = asBool(); + if (boolean == nullptr) { return false; } - value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); + value = boolean->getVal(); return true; } @@ -474,8 +518,9 @@ QPDFObjectHandle::getValueAsBool(bool& value) long long QPDFObjectHandle::getIntValue() { - if (isInteger()) { - return dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); + auto integer = asInteger(); + if (integer) { + return integer->getVal(); } else { typeWarning("integer", "returning 0"); QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); @@ -486,10 +531,11 @@ QPDFObjectHandle::getIntValue() bool QPDFObjectHandle::getValueAsInt(long long& value) { - if (!isInteger()) { + auto integer = asInteger(); + if (integer == nullptr) { return false; } - value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); + value = integer->getVal(); return true; } @@ -585,8 +631,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int& value) std::string QPDFObjectHandle::getRealValue() { - if (isReal()) { - return dynamic_cast<QPDF_Real*>(obj.get())->getVal(); + auto real = asReal(); + if (real) { + return real->getVal(); } else { typeWarning("real", "returning 0.0"); QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0"); @@ -597,10 +644,11 @@ QPDFObjectHandle::getRealValue() bool QPDFObjectHandle::getValueAsReal(std::string& value) { - if (!isReal()) { + auto real = asReal(); + if (real == nullptr) { return false; } - value = dynamic_cast<QPDF_Real*>(obj.get())->getVal(); + value = real->getVal(); return true; } @@ -609,8 +657,9 @@ QPDFObjectHandle::getValueAsReal(std::string& value) std::string QPDFObjectHandle::getName() { - if (isName()) { - return dynamic_cast<QPDF_Name*>(obj.get())->getName(); + auto name = asName(); + if (name) { + return name->getName(); } else { typeWarning("name", "returning dummy name"); QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); @@ -621,10 +670,11 @@ QPDFObjectHandle::getName() bool QPDFObjectHandle::getValueAsName(std::string& value) { - if (!isName()) { + auto name = asName(); + if (name == nullptr) { return false; } - value = dynamic_cast<QPDF_Name*>(obj.get())->getName(); + value = name->getName(); return true; } @@ -633,8 +683,9 @@ QPDFObjectHandle::getValueAsName(std::string& value) std::string QPDFObjectHandle::getStringValue() { - if (isString()) { - return dynamic_cast<QPDF_String*>(obj.get())->getVal(); + auto str = asString(); + if (str) { + return str->getVal(); } else { typeWarning("string", "returning empty string"); QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); @@ -645,18 +696,20 @@ QPDFObjectHandle::getStringValue() bool QPDFObjectHandle::getValueAsString(std::string& value) { - if (!isString()) { + auto str = asString(); + if (str == nullptr) { return false; } - value = dynamic_cast<QPDF_String*>(obj.get())->getVal(); + value = str->getVal(); return true; } std::string QPDFObjectHandle::getUTF8Value() { - if (isString()) { - return dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); + auto str = asString(); + if (str) { + return str->getUTF8Val(); } else { typeWarning("string", "returning empty string"); QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); @@ -667,10 +720,11 @@ QPDFObjectHandle::getUTF8Value() bool QPDFObjectHandle::getValueAsUTF8(std::string& value) { - if (!isString()) { + auto str = asString(); + if (str == nullptr) { return false; } - value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); + value = str->getUTF8Val(); return true; } @@ -679,8 +733,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string& value) std::string QPDFObjectHandle::getOperatorValue() { - if (isOperator()) { - return dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); + auto op = asOperator(); + if (op) { + return op->getVal(); } else { typeWarning("operator", "returning fake value"); QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value"); @@ -691,18 +746,20 @@ QPDFObjectHandle::getOperatorValue() bool QPDFObjectHandle::getValueAsOperator(std::string& value) { - if (!isOperator()) { + auto op = asOperator(); + if (op == nullptr) { return false; } - value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); + value = op->getVal(); return true; } std::string QPDFObjectHandle::getInlineImageValue() { - if (isInlineImage()) { - return dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); + auto image = asInlineImage(); + if (image) { + return image->getVal(); } else { typeWarning("inlineimage", "returning empty data"); QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data"); @@ -713,10 +770,11 @@ QPDFObjectHandle::getInlineImageValue() bool QPDFObjectHandle::getValueAsInlineImage(std::string& value) { - if (!isInlineImage()) { + auto image = asInlineImage(); + if (image == nullptr) { return false; } - value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); + value = image->getVal(); return true; } @@ -731,8 +789,9 @@ QPDFObjectHandle::aitems() int QPDFObjectHandle::getArrayNItems() { - if (isArray()) { - return dynamic_cast<QPDF_Array*>(obj.get())->getNItems(); + auto array = asArray(); + if (array) { + return array->getNItems(); } else { typeWarning("array", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); @@ -744,11 +803,12 @@ QPDFObjectHandle QPDFObjectHandle::getArrayItem(int n) { QPDFObjectHandle result; - if (isArray() && (n < getArrayNItems()) && (n >= 0)) { - result = dynamic_cast<QPDF_Array*>(obj.get())->getItem(n); + auto array = asArray(); + if (array && (n < array->getNItems()) && (n >= 0)) { + result = array->getItem(n); } else { result = newNull(); - if (isArray()) { + if (array) { objectWarning("returning null for out of bounds array access"); QTC::TC("qpdf", "QPDFObjectHandle array bounds"); } else { @@ -757,7 +817,7 @@ QPDFObjectHandle::getArrayItem(int n) } QPDF* context = nullptr; std::string description; - if (this->obj->getDescription(context, description)) { + if (obj->getDescription(context, description)) { result.setObjectDescription( context, description + " -> null returned from invalid array access"); @@ -769,14 +829,12 @@ QPDFObjectHandle::getArrayItem(int n) bool QPDFObjectHandle::isRectangle() { - if (!isArray()) { - return false; - } - if (getArrayNItems() != 4) { + auto array = asArray(); + if ((array == nullptr) || (array->getNItems() != 4)) { return false; } for (int i = 0; i < 4; ++i) { - if (!getArrayItem(i).isNumber()) { + if (!array->getItem(i).isNumber()) { return false; } } @@ -786,14 +844,12 @@ QPDFObjectHandle::isRectangle() bool QPDFObjectHandle::isMatrix() { - if (!isArray()) { - return false; - } - if (getArrayNItems() != 6) { + auto array = asArray(); + if ((array == nullptr) || (array->getNItems() != 6)) { return false; } for (int i = 0; i < 6; ++i) { - if (!getArrayItem(i).isNumber()) { + if (!array->getItem(i).isNumber()) { return false; } } @@ -805,13 +861,14 @@ QPDFObjectHandle::getArrayAsRectangle() { Rectangle result; if (isRectangle()) { + auto array = asArray(); // Rectangle coordinates are always supposed to be llx, lly, // urx, ury, but files have been found in the wild where // llx > urx or lly > ury. - double i0 = getArrayItem(0).getNumericValue(); - double i1 = getArrayItem(1).getNumericValue(); - double i2 = getArrayItem(2).getNumericValue(); - double i3 = getArrayItem(3).getNumericValue(); + double i0 = array->getItem(0).getNumericValue(); + double i1 = array->getItem(1).getNumericValue(); + double i2 = array->getItem(2).getNumericValue(); + double i3 = array->getItem(3).getNumericValue(); result = Rectangle( std::min(i0, i2), std::min(i1, i3), @@ -826,13 +883,14 @@ QPDFObjectHandle::getArrayAsMatrix() { Matrix result; if (isMatrix()) { + auto array = asArray(); result = Matrix( - getArrayItem(0).getNumericValue(), - getArrayItem(1).getNumericValue(), - getArrayItem(2).getNumericValue(), - getArrayItem(3).getNumericValue(), - getArrayItem(4).getNumericValue(), - getArrayItem(5).getNumericValue()); + array->getItem(0).getNumericValue(), + array->getItem(1).getNumericValue(), + array->getItem(2).getNumericValue(), + array->getItem(3).getNumericValue(), + array->getItem(4).getNumericValue(), + array->getItem(5).getNumericValue()); } return result; } @@ -841,8 +899,9 @@ std::vector<QPDFObjectHandle> QPDFObjectHandle::getArrayAsVector() { std::vector<QPDFObjectHandle> result; - if (isArray()) { - dynamic_cast<QPDF_Array*>(obj.get())->getAsVector(result); + auto array = asArray(); + if (array) { + array->getAsVector(result); } else { typeWarning("array", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); @@ -855,9 +914,10 @@ QPDFObjectHandle::getArrayAsVector() void QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) { - if (isArray()) { + auto array = asArray(); + if (array) { checkOwnership(item); - dynamic_cast<QPDF_Array*>(obj.get())->setItem(n, item); + array->setItem(n, item); } else { typeWarning("array", "ignoring attempt to set item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); @@ -867,11 +927,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) void QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) { - if (isArray()) { + auto array = asArray(); + if (array) { for (auto const& item: items) { checkOwnership(item); } - dynamic_cast<QPDF_Array*>(obj.get())->setFromVector(items); + array->setFromVector(items); } else { typeWarning("array", "ignoring attempt to replace items"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); @@ -881,8 +942,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) void QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) { - if (isArray()) { - dynamic_cast<QPDF_Array*>(obj.get())->insertItem(at, item); + auto array = asArray(); + if (array) { + array->insertItem(at, item); } else { typeWarning("array", "ignoring attempt to insert item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); @@ -899,9 +961,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const& item) void QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) { - if (isArray()) { + auto array = asArray(); + if (array) { checkOwnership(item); - dynamic_cast<QPDF_Array*>(obj.get())->appendItem(item); + array->appendItem(item); } else { typeWarning("array", "ignoring attempt to append item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); @@ -918,10 +981,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) void QPDFObjectHandle::eraseItem(int at) { - if (isArray() && (at < getArrayNItems()) && (at >= 0)) { - dynamic_cast<QPDF_Array*>(obj.get())->eraseItem(at); + auto array = asArray(); + if (array && (at < array->getNItems()) && (at >= 0)) { + array->eraseItem(at); } else { - if (isArray()) { + if (array) { objectWarning("ignoring attempt to erase out of bounds array item"); QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); } else { @@ -935,8 +999,9 @@ QPDFObjectHandle QPDFObjectHandle::eraseItemAndGetOld(int at) { auto result = QPDFObjectHandle::newNull(); - if (isArray() && (at < getArrayNItems()) && (at >= 0)) { - result = getArrayItem(at); + auto array = asArray(); + if (array && (at < array->getNItems()) && (at >= 0)) { + result = array->getItem(at); } eraseItem(at); return result; @@ -953,8 +1018,9 @@ QPDFObjectHandle::ditems() bool QPDFObjectHandle::hasKey(std::string const& key) { - if (isDictionary()) { - return dynamic_cast<QPDF_Dictionary*>(obj.get())->hasKey(key); + auto dict = asDictionary(); + if (dict) { + return dict->hasKey(key); } else { typeWarning( "dictionary", "returning false for a key containment request"); @@ -967,15 +1033,16 @@ QPDFObjectHandle QPDFObjectHandle::getKey(std::string const& key) { QPDFObjectHandle result; - if (isDictionary()) { - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKey(key); + auto dict = asDictionary(); + if (dict) { + result = dict->getKey(key); } else { typeWarning("dictionary", "returning null for attempted key retrieval"); QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); result = newNull(); QPDF* qpdf = nullptr; std::string description; - if (this->obj->getDescription(qpdf, description)) { + if (obj->getDescription(qpdf, description)) { result.setObjectDescription( qpdf, (description + " -> null returned from getting key " + key + @@ -995,8 +1062,9 @@ std::set<std::string> QPDFObjectHandle::getKeys() { std::set<std::string> result; - if (isDictionary()) { - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKeys(); + auto dict = asDictionary(); + if (dict) { + result = dict->getKeys(); } else { typeWarning("dictionary", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); @@ -1008,8 +1076,9 @@ std::map<std::string, QPDFObjectHandle> QPDFObjectHandle::getDictAsMap() { std::map<std::string, QPDFObjectHandle> result; - if (isDictionary()) { - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getAsMap(); + auto dict = asDictionary(); + if (dict) { + result = dict->getAsMap(); } else { typeWarning("dictionary", "treating as empty"); QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); @@ -1200,9 +1269,10 @@ void QPDFObjectHandle::replaceKey( std::string const& key, QPDFObjectHandle const& value) { - if (isDictionary()) { + auto dict = asDictionary(); + if (dict) { checkOwnership(value); - dynamic_cast<QPDF_Dictionary*>(obj.get())->replaceKey(key, value); + dict->replaceKey(key, value); } else { typeWarning("dictionary", "ignoring key replacement request"); QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); @@ -1229,8 +1299,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( void QPDFObjectHandle::removeKey(std::string const& key) { - if (isDictionary()) { - dynamic_cast<QPDF_Dictionary*>(obj.get())->removeKey(key); + auto dict = asDictionary(); + if (dict) { + dict->removeKey(key); } else { typeWarning("dictionary", "ignoring key removal request"); QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); @@ -1241,8 +1312,9 @@ QPDFObjectHandle QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) { auto result = QPDFObjectHandle::newNull(); - if (isDictionary()) { - result = getKey(key); + auto dict = asDictionary(); + if (dict) { + result = dict->getKey(key); } removeKey(key); return result; @@ -1259,50 +1331,43 @@ QPDFObjectHandle::replaceOrRemoveKey( QPDFObjectHandle QPDFObjectHandle::getDict() { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->getDict(); + return asStreamWithAssert()->getDict(); } void QPDFObjectHandle::setFilterOnWrite(bool val) { - assertStream(); - dynamic_cast<QPDF_Stream*>(obj.get())->setFilterOnWrite(val); + asStreamWithAssert()->setFilterOnWrite(val); } bool QPDFObjectHandle::getFilterOnWrite() { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->getFilterOnWrite(); + return asStreamWithAssert()->getFilterOnWrite(); } bool QPDFObjectHandle::isDataModified() { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->isDataModified(); + return asStreamWithAssert()->isDataModified(); } void QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict) { - assertStream(); - dynamic_cast<QPDF_Stream*>(obj.get())->replaceDict(new_dict); + asStreamWithAssert()->replaceDict(new_dict); } std::shared_ptr<Buffer> QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamData(level); + return asStreamWithAssert()->getStreamData(level); } std::shared_ptr<Buffer> QPDFObjectHandle::getRawStreamData() { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->getRawStreamData(); + return asStreamWithAssert()->getRawStreamData(); } bool @@ -1314,8 +1379,7 @@ QPDFObjectHandle::pipeStreamData( bool suppress_warnings, bool will_retry) { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( + return asStreamWithAssert()->pipeStreamData( p, filtering_attempted, encode_flags, @@ -1332,9 +1396,8 @@ QPDFObjectHandle::pipeStreamData( bool suppress_warnings, bool will_retry) { - assertStream(); bool filtering_attempted; - dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( + asStreamWithAssert()->pipeStreamData( p, &filtering_attempted, encode_flags, @@ -1368,9 +1431,7 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( - data, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(data, filter, decode_parms); } void @@ -1379,14 +1440,12 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto b = std::make_shared<Buffer>(data.length()); unsigned char* bp = b->getBuffer(); if (bp) { memcpy(bp, data.c_str(), data.length()); } - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( - b, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(b, filter, decode_parms); } void @@ -1395,9 +1454,7 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( - provider, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(provider, filter, decode_parms); } namespace @@ -1446,11 +1503,9 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto sdp = std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( - sdp, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); } void @@ -1459,11 +1514,9 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto sdp = std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData( - sdp, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); } std::map<std::string, QPDFObjectHandle> @@ -1478,10 +1531,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( { all_description = description; std::vector<QPDFObjectHandle> result; - if (isArray()) { - int n_items = getArrayNItems(); + auto array = asArray(); + if (array) { + int n_items = array->getNItems(); for (int i = 0; i < n_items; ++i) { - QPDFObjectHandle item = getArrayItem(i); + QPDFObjectHandle item = array->getItem(i); if (item.isStream()) { result.push_back(item); } else { @@ -1648,18 +1702,16 @@ QPDFObjectHandle::unparseResolved() if (!dereference()) { throw std::logic_error( "attempted to dereference an uninitialized QPDFObjectHandle"); - } else if (this->reserved) { - throw std::logic_error( - "QPDFObjectHandle: attempting to unparse a reserved object"); } - return this->obj->unparse(); + return obj->unparse(); } std::string QPDFObjectHandle::unparseBinary() { - if (this->isString()) { - return dynamic_cast<QPDF_String*>(this->obj.get())->unparse(true); + auto str = asString(); + if (str) { + return str->unparse(true); } else { return unparse(); } @@ -1675,16 +1727,13 @@ QPDFObjectHandle::getJSON(bool dereference_indirect) JSON QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) { - if ((!dereference_indirect) && this->isIndirect()) { + if ((!dereference_indirect) && isIndirect()) { return JSON::makeString(unparse()); } else if (!dereference()) { throw std::logic_error( "attempted to dereference an uninitialized QPDFObjectHandle"); - } else if (this->reserved) { - throw std::logic_error( - "QPDFObjectHandle: attempting to unparse a reserved object"); } else { - return this->obj->getJSON(json_version); + return obj->getJSON(json_version); } } @@ -1696,8 +1745,7 @@ QPDFObjectHandle::getStreamJSON( Pipeline* p, std::string const& data_filename) { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamJSON( + return asStreamWithAssert()->getStreamJSON( json_version, json_data, decode_level, p, data_filename); } @@ -1917,8 +1965,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr<TokenFilter> filter) void QPDFObjectHandle::addTokenFilter(std::shared_ptr<TokenFilter> filter) { - assertStream(); - return dynamic_cast<QPDF_Stream*>(obj.get())->addTokenFilter(filter); + return asStreamWithAssert()->addTokenFilter(filter); } QPDFObjectHandle @@ -1945,21 +1992,6 @@ QPDFObjectHandle::getParsedOffset() } QPDFObjectHandle -QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og) -{ - if (!og.isIndirect()) { - // Special case: QPDF uses objid 0 as a sentinel for direct - // objects, and the PDF specification doesn't allow for object - // 0. Treat indirect references to object 0 as null so that we - // never create an indirect object with objid 0. - QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid"); - return newNull(); - } - - return QPDFObjectHandle(qpdf, og); -} - -QPDFObjectHandle QPDFObjectHandle::newBool(bool value) { return QPDFObjectHandle(QPDF_Bool::create(value)); @@ -2128,8 +2160,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) QPDFObjectHandle stream_dict = newDictionary(); QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0))); - result.dereference(); - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get()); + auto stream = result.asStream(); stream->setObjGen(result.getObjGen()); return result; } @@ -2155,18 +2186,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf, std::string const& data) 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(makeReserved()); - QPDFObjectHandle result = newIndirect(qpdf, reserved.getObjGen()); - result.reserved = true; - return result; -} - -QPDFObjectHandle -QPDFObjectHandle::makeReserved() -{ - return QPDFObjectHandle(QPDF_Reserved::create()); + return qpdf->makeIndirectObject(QPDFObjectHandle(QPDF_Reserved::create())); } void @@ -2212,12 +2232,7 @@ QPDFObjectHandle::shallowCopyInternal( QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream"); throw std::runtime_error("attempt to make a shallow copy of a stream"); } - - if (isArray() || isDictionary()) { - new_obj = QPDFObjectHandle(obj->shallowCopy()); - } else { - new_obj = *this; - } + new_obj = QPDFObjectHandle(obj->shallowCopy()); std::set<QPDFObjGen> visited; new_obj.copyObject(visited, false, first_level_only, false); @@ -2258,9 +2273,6 @@ QPDFObjectHandle::copyObject( " reserved object handle direct"); } - qpdf = nullptr; - og = QPDFObjGen(); - std::shared_ptr<QPDFObject> new_obj; if (isBool() || isInteger() || isName() || isNull() || isReal() || @@ -2268,9 +2280,10 @@ QPDFObjectHandle::copyObject( new_obj = obj->shallowCopy(); } else if (isArray()) { std::vector<QPDFObjectHandle> items; - int n = getArrayNItems(); + auto array = asArray(); + int n = array->getNItems(); for (int i = 0; i < n; ++i) { - items.push_back(getArrayItem(i)); + items.push_back(array->getItem(i)); if ((!first_level_only) && (cross_indirect || (!items.back().isIndirect()))) { items.back().copyObject( @@ -2280,8 +2293,9 @@ QPDFObjectHandle::copyObject( new_obj = QPDF_Array::create(items); } else if (isDictionary()) { std::map<std::string, QPDFObjectHandle> items; + auto dict = asDictionary(); for (auto const& key: getKeys()) { - items[key] = getKey(key); + items[key] = dict->getKey(key); if ((!first_level_only) && (cross_indirect || (!items[key].isIndirect()))) { items[key].copyObject( @@ -2329,7 +2343,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) void QPDFObjectHandle::assertInitialized() const { - if (!this->initialized) { + if (!isInitialized()) { throw std::logic_error("operation attempted on uninitialized " "QPDFObjectHandle"); } @@ -2544,8 +2558,9 @@ QPDFObjectHandle::isImage(bool exclude_imagemask) void QPDFObjectHandle::checkOwnership(QPDFObjectHandle const& item) const { - if ((this->qpdf != nullptr) && (item.qpdf != nullptr) && - (this->qpdf != item.qpdf)) { + auto qpdf = getOwningQPDF(); + auto item_qpdf = item.getOwningQPDF(); + if ((qpdf != nullptr) && (item_qpdf != nullptr) && (qpdf != item_qpdf)) { QTC::TC("qpdf", "QPDFObjectHandle check ownership"); throw std::logic_error( "Attempting to add an object from a different QPDF." @@ -2564,28 +2579,10 @@ QPDFObjectHandle::assertPageObject() bool QPDFObjectHandle::dereference() { - if (!this->initialized) { + if (!isInitialized()) { return false; } - if (this->obj.get() && getObjectID() && - QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj)) { - this->obj = nullptr; - } - if (this->obj == nullptr) { - std::shared_ptr<QPDFObject> obj = - QPDF::Resolver::resolve(this->qpdf, getObjGen()); - if (obj == nullptr) { - // QPDF::resolve never returns an uninitialized object, but - // check just in case. - this->obj = QPDF_Null::create(); - } else if (dynamic_cast<QPDF_Reserved*>(obj.get())) { - // Do not resolve - this->reserved = true; - } else { - this->reserved = false; - this->obj = obj; - } - } + this->obj->resolve(); return true; } diff --git a/libqpdf/QPDFParser.cc b/libqpdf/QPDFParser.cc index ccdd9db0..9aa1f426 100644 --- a/libqpdf/QPDFParser.cc +++ b/libqpdf/QPDFParser.cc @@ -1,8 +1,8 @@ #include <qpdf/QPDFParser.hh> #include <qpdf/QPDF.hh> +#include <qpdf/QPDFObjGen.hh> #include <qpdf/QPDFObjectHandle.hh> -#include <qpdf/QPDF_Array.hh> #include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> @@ -55,6 +55,7 @@ QPDFParser::parse(bool& empty, bool content_stream) while (!done) { bool bad = false; + bool indirect_ref = false; is_null = false; auto& frame = stack.back(); auto& olist = frame.olist; @@ -185,12 +186,16 @@ QPDFParser::parse(bool& empty, bool content_stream) "QPDFObjectHandle::parse called without context" " on an object with indirect references"); } - // Try to resolve indirect objects - object = QPDFObjectHandle::newIndirect( - context, - QPDFObjGen( - olist.at(size - 2).getIntValueAsInt(), - olist.back().getIntValueAsInt())); + auto ref_og = QPDFObjGen( + olist.at(size - 2).getIntValueAsInt(), + olist.back().getIntValueAsInt()); + if (ref_og.isIndirect()) { + object = context->getObject(ref_og); + indirect_ref = true; + } else { + QTC::TC("qpdf", "QPDFParser indirect with 0 objid"); + is_null = true; + } olist.pop_back(); olist.pop_back(); } else if ((value == "endobj") && (state == st_top)) { @@ -274,8 +279,8 @@ QPDFParser::parse(bool& empty, bool content_stream) case st_dictionary: case st_array: - if (!object.isDirectNull()) { - // No need to set description for direct nulls- they will + if (!indirect_ref && !object.isDirectNull()) { + // No need to set description for direct nulls - they will // become implicit. setDescriptionFromInput(object, input->getLastOffset()); object.setParsedOffset(input->getLastOffset()); diff --git a/libqpdf/QPDFValue.cc b/libqpdf/QPDFValue.cc new file mode 100644 index 00000000..8a6222d2 --- /dev/null +++ b/libqpdf/QPDFValue.cc @@ -0,0 +1,11 @@ +#include <qpdf/QPDFValue.hh> + +#include <qpdf/QPDFObject.hh> + +std::shared_ptr<QPDFObject> +QPDFValue::do_create(QPDFValue* object) +{ + std::shared_ptr<QPDFObject> obj(new QPDFObject()); + obj->value = std::shared_ptr<QPDFValue>(object); + return obj; +} diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 55e4d20a..63fe98d4 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -4,12 +4,14 @@ #include <qpdf/QUtil.hh> #include <stdexcept> -QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) +QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) : + QPDFValue(::ot_array, "array") { setFromVector(v); } QPDF_Array::QPDF_Array(SparseOHArray const& items) : + QPDFValue(::ot_array, "array"), elements(items) { } @@ -62,18 +64,6 @@ QPDF_Array::getJSON(int json_version) return j; } -QPDFObject::object_type_e -QPDF_Array::getTypeCode() const -{ - return QPDFObject::ot_array; -} - -char const* -QPDF_Array::getTypeName() const -{ - return "array"; -} - int QPDF_Array::getNItems() const { diff --git a/libqpdf/QPDF_Bool.cc b/libqpdf/QPDF_Bool.cc index f26325c3..efbfd6c9 100644 --- a/libqpdf/QPDF_Bool.cc +++ b/libqpdf/QPDF_Bool.cc @@ -1,6 +1,7 @@ #include <qpdf/QPDF_Bool.hh> QPDF_Bool::QPDF_Bool(bool val) : + QPDFValue(::ot_boolean, "boolean"), val(val) { } @@ -29,18 +30,6 @@ QPDF_Bool::getJSON(int json_version) return JSON::makeBool(this->val); } -QPDFObject::object_type_e -QPDF_Bool::getTypeCode() const -{ - return QPDFObject::ot_boolean; -} - -char const* -QPDF_Bool::getTypeName() const -{ - return "boolean"; -} - bool QPDF_Bool::getVal() const { diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc index 60b2339f..845bcad8 100644 --- a/libqpdf/QPDF_Dictionary.cc +++ b/libqpdf/QPDF_Dictionary.cc @@ -1,10 +1,10 @@ #include <qpdf/QPDF_Dictionary.hh> #include <qpdf/QPDF_Name.hh> -#include <qpdf/QPDF_Null.hh> QPDF_Dictionary::QPDF_Dictionary( std::map<std::string, QPDFObjectHandle> const& items) : + QPDFValue(::ot_dictionary, "dictionary"), items(items) { } @@ -58,18 +58,6 @@ QPDF_Dictionary::getJSON(int json_version) return j; } -QPDFObject::object_type_e -QPDF_Dictionary::getTypeCode() const -{ - return QPDFObject::ot_dictionary; -} - -char const* -QPDF_Dictionary::getTypeName() const -{ - return "dictionary"; -} - bool QPDF_Dictionary::hasKey(std::string const& key) { diff --git a/libqpdf/QPDF_InlineImage.cc b/libqpdf/QPDF_InlineImage.cc index c3c656e0..76318196 100644 --- a/libqpdf/QPDF_InlineImage.cc +++ b/libqpdf/QPDF_InlineImage.cc @@ -1,6 +1,7 @@ #include <qpdf/QPDF_InlineImage.hh> QPDF_InlineImage::QPDF_InlineImage(std::string const& val) : + QPDFValue(::ot_inlineimage, "inline-image"), val(val) { } @@ -29,18 +30,6 @@ QPDF_InlineImage::getJSON(int json_version) return JSON::makeNull(); } -QPDFObject::object_type_e -QPDF_InlineImage::getTypeCode() const -{ - return QPDFObject::ot_inlineimage; -} - -char const* -QPDF_InlineImage::getTypeName() const -{ - return "inline-image"; -} - std::string QPDF_InlineImage::getVal() const { diff --git a/libqpdf/QPDF_Integer.cc b/libqpdf/QPDF_Integer.cc index e8d23e4a..24812573 100644 --- a/libqpdf/QPDF_Integer.cc +++ b/libqpdf/QPDF_Integer.cc @@ -3,6 +3,7 @@ #include <qpdf/QUtil.hh> QPDF_Integer::QPDF_Integer(long long val) : + QPDFValue(::ot_integer, "integer"), val(val) { } @@ -31,18 +32,6 @@ QPDF_Integer::getJSON(int json_version) return JSON::makeInt(this->val); } -QPDFObject::object_type_e -QPDF_Integer::getTypeCode() const -{ - return QPDFObject::ot_integer; -} - -char const* -QPDF_Integer::getTypeName() const -{ - return "integer"; -} - long long QPDF_Integer::getVal() const { diff --git a/libqpdf/QPDF_Name.cc b/libqpdf/QPDF_Name.cc index 73990775..c86d34b4 100644 --- a/libqpdf/QPDF_Name.cc +++ b/libqpdf/QPDF_Name.cc @@ -5,6 +5,7 @@ #include <string.h> QPDF_Name::QPDF_Name(std::string const& name) : + QPDFValue(::ot_name, "name"), name(name) { } @@ -61,18 +62,6 @@ QPDF_Name::getJSON(int json_version) } } -QPDFObject::object_type_e -QPDF_Name::getTypeCode() const -{ - return QPDFObject::ot_name; -} - -char const* -QPDF_Name::getTypeName() const -{ - return "name"; -} - std::string QPDF_Name::getName() const { diff --git a/libqpdf/QPDF_Null.cc b/libqpdf/QPDF_Null.cc index b015ed8b..f60dda1f 100644 --- a/libqpdf/QPDF_Null.cc +++ b/libqpdf/QPDF_Null.cc @@ -1,5 +1,10 @@ #include <qpdf/QPDF_Null.hh> +QPDF_Null::QPDF_Null() : + QPDFValue(::ot_null, "null") +{ +} + std::shared_ptr<QPDFObject> QPDF_Null::create() { @@ -23,15 +28,3 @@ QPDF_Null::getJSON(int json_version) { return JSON::makeNull(); } - -QPDFObject::object_type_e -QPDF_Null::getTypeCode() const -{ - return QPDFObject::ot_null; -} - -char const* -QPDF_Null::getTypeName() const -{ - return "null"; -} diff --git a/libqpdf/QPDF_Operator.cc b/libqpdf/QPDF_Operator.cc index cd5009ae..547ff40a 100644 --- a/libqpdf/QPDF_Operator.cc +++ b/libqpdf/QPDF_Operator.cc @@ -1,6 +1,7 @@ #include <qpdf/QPDF_Operator.hh> QPDF_Operator::QPDF_Operator(std::string const& val) : + QPDFValue(::ot_operator, "operator"), val(val) { } @@ -20,7 +21,7 @@ QPDF_Operator::shallowCopy() std::string QPDF_Operator::unparse() { - return this->val; + return val; } JSON @@ -29,18 +30,6 @@ QPDF_Operator::getJSON(int json_version) return JSON::makeNull(); } -QPDFObject::object_type_e -QPDF_Operator::getTypeCode() const -{ - return QPDFObject::ot_operator; -} - -char const* -QPDF_Operator::getTypeName() const -{ - return "operator"; -} - std::string QPDF_Operator::getVal() const { diff --git a/libqpdf/QPDF_Real.cc b/libqpdf/QPDF_Real.cc index 138bbb3c..85c9ceeb 100644 --- a/libqpdf/QPDF_Real.cc +++ b/libqpdf/QPDF_Real.cc @@ -3,12 +3,14 @@ #include <qpdf/QUtil.hh> QPDF_Real::QPDF_Real(std::string const& val) : + QPDFValue(::ot_real, "real"), val(val) { } QPDF_Real::QPDF_Real( double value, int decimal_places, bool trim_trailing_zeroes) : + QPDFValue(::ot_real, "real"), val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes)) { } @@ -60,18 +62,6 @@ QPDF_Real::getJSON(int json_version) return JSON::makeNumber(result); } -QPDFObject::object_type_e -QPDF_Real::getTypeCode() const -{ - return QPDFObject::ot_real; -} - -char const* -QPDF_Real::getTypeName() const -{ - return "real"; -} - std::string QPDF_Real::getVal() { diff --git a/libqpdf/QPDF_Reserved.cc b/libqpdf/QPDF_Reserved.cc index 5808a369..f5af4688 100644 --- a/libqpdf/QPDF_Reserved.cc +++ b/libqpdf/QPDF_Reserved.cc @@ -2,6 +2,11 @@ #include <stdexcept> +QPDF_Reserved::QPDF_Reserved() : + QPDFValue(::ot_reserved, "reserved") +{ +} + std::shared_ptr<QPDFObject> QPDF_Reserved::create() { @@ -17,25 +22,15 @@ QPDF_Reserved::shallowCopy() std::string QPDF_Reserved::unparse() { - throw std::logic_error("attempt to unparse QPDF_Reserved"); + throw std::logic_error( + "QPDFObjectHandle: attempting to unparse a reserved object"); return ""; } JSON QPDF_Reserved::getJSON(int json_version) { - throw std::logic_error("attempt to generate JSON from QPDF_Reserved"); + throw std::logic_error( + "QPDFObjectHandle: attempting to unparse a reserved object"); return JSON::makeNull(); } - -QPDFObject::object_type_e -QPDF_Reserved::getTypeCode() const -{ - return QPDFObject::ot_reserved; -} - -char const* -QPDF_Reserved::getTypeName() const -{ - return "reserved"; -} diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 1b7f9461..9932c15d 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -114,6 +114,7 @@ QPDF_Stream::QPDF_Stream( QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) : + QPDFValue(::ot_stream, "stream"), qpdf(qpdf), og(og), filter_on_write(true), @@ -291,22 +292,10 @@ QPDF_Stream::getStreamJSON( return result; } -QPDFObject::object_type_e -QPDF_Stream::getTypeCode() const -{ - return QPDFObject::ot_stream; -} - -char const* -QPDF_Stream::getTypeName() const -{ - return "stream"; -} - void QPDF_Stream::setDescription(QPDF* qpdf, std::string const& description) { - this->QPDFObject::setDescription(qpdf, description); + this->QPDFValue::setDescription(qpdf, description); setDictDescription(); } diff --git a/libqpdf/QPDF_String.cc b/libqpdf/QPDF_String.cc index b038366b..c6cb6c41 100644 --- a/libqpdf/QPDF_String.cc +++ b/libqpdf/QPDF_String.cc @@ -21,6 +21,7 @@ is_iso_latin1_printable(char ch) } QPDF_String::QPDF_String(std::string const& val) : + QPDFValue(::ot_string, "string"), val(val) { } @@ -84,18 +85,6 @@ QPDF_String::getJSON(int json_version) return JSON::makeString(result); } -QPDFObject::object_type_e -QPDF_String::getTypeCode() const -{ - return QPDFObject::ot_string; -} - -char const* -QPDF_String::getTypeName() const -{ - return "string"; -} - bool QPDF_String::useHexString() const { diff --git a/libqpdf/QPDF_Unresolved.cc b/libqpdf/QPDF_Unresolved.cc new file mode 100644 index 00000000..f824a9a6 --- /dev/null +++ b/libqpdf/QPDF_Unresolved.cc @@ -0,0 +1,36 @@ +#include <qpdf/QPDF_Unresolved.hh> + +#include <stdexcept> + +QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og) : + QPDFValue(::ot_unresolved, "unresolved", qpdf, og) +{ +} + +std::shared_ptr<QPDFObject> +QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og) +{ + return do_create(new QPDF_Unresolved(qpdf, og)); +} + +std::shared_ptr<QPDFObject> +QPDF_Unresolved::shallowCopy() +{ + throw std::logic_error( + "attempted to shallow copy unresolved QPDFObjectHandle"); + return create(qpdf, og); +} + +std::string +QPDF_Unresolved::unparse() +{ + throw std::logic_error( + "attempted to unparse an unresolved QPDFObjectHandle"); + return ""; +} + +JSON +QPDF_Unresolved::getJSON(int json_version) +{ + return JSON::makeNull(); +} diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index e988092e..e09f7b68 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -137,8 +137,7 @@ QPDF::isLinearized() return false; } - QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect( - this, QPDFObjGen(lindict_obj, 0)); + auto candidate = getObjectByID(lindict_obj, 0); if (!candidate.isDictionary()) { return false; } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 3e095637..426efe36 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -1,13 +1,13 @@ #ifndef QPDF_ARRAY_HH #define QPDF_ARRAY_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> #include <qpdf/SparseOHArray.hh> #include <list> #include <vector> -class QPDF_Array: public QPDFObject +class QPDF_Array: public QPDFValue { public: virtual ~QPDF_Array() = default; @@ -17,8 +17,6 @@ class QPDF_Array: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; int getNItems() const; QPDFObjectHandle getItem(int n) const; diff --git a/libqpdf/qpdf/QPDF_Bool.hh b/libqpdf/qpdf/QPDF_Bool.hh index dbedc70a..3e45cd8e 100644 --- a/libqpdf/qpdf/QPDF_Bool.hh +++ b/libqpdf/qpdf/QPDF_Bool.hh @@ -1,9 +1,9 @@ #ifndef QPDF_BOOL_HH #define QPDF_BOOL_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Bool: public QPDFObject +class QPDF_Bool: public QPDFValue { public: virtual ~QPDF_Bool() = default; @@ -11,8 +11,6 @@ class QPDF_Bool: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; bool getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Dictionary.hh b/libqpdf/qpdf/QPDF_Dictionary.hh index cacc8961..19ab8d9b 100644 --- a/libqpdf/qpdf/QPDF_Dictionary.hh +++ b/libqpdf/qpdf/QPDF_Dictionary.hh @@ -1,14 +1,14 @@ #ifndef QPDF_DICTIONARY_HH #define QPDF_DICTIONARY_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> #include <map> #include <set> #include <qpdf/QPDFObjectHandle.hh> -class QPDF_Dictionary: public QPDFObject +class QPDF_Dictionary: public QPDFValue { public: virtual ~QPDF_Dictionary() = default; @@ -17,8 +17,6 @@ class QPDF_Dictionary: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; // hasKey() and getKeys() treat keys with null values as if they // aren't there. getKey() returns null for the value of a diff --git a/libqpdf/qpdf/QPDF_InlineImage.hh b/libqpdf/qpdf/QPDF_InlineImage.hh index caaeaf87..b7bea9c7 100644 --- a/libqpdf/qpdf/QPDF_InlineImage.hh +++ b/libqpdf/qpdf/QPDF_InlineImage.hh @@ -1,9 +1,9 @@ #ifndef QPDF_INLINEIMAGE_HH #define QPDF_INLINEIMAGE_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_InlineImage: public QPDFObject +class QPDF_InlineImage: public QPDFValue { public: virtual ~QPDF_InlineImage() = default; @@ -11,8 +11,6 @@ class QPDF_InlineImage: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; std::string getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Integer.hh b/libqpdf/qpdf/QPDF_Integer.hh index 2c17daf0..7e09673c 100644 --- a/libqpdf/qpdf/QPDF_Integer.hh +++ b/libqpdf/qpdf/QPDF_Integer.hh @@ -1,9 +1,9 @@ #ifndef QPDF_INTEGER_HH #define QPDF_INTEGER_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Integer: public QPDFObject +class QPDF_Integer: public QPDFValue { public: virtual ~QPDF_Integer() = default; @@ -11,8 +11,6 @@ class QPDF_Integer: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; long long getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Name.hh b/libqpdf/qpdf/QPDF_Name.hh index cf653b2e..74fc7e44 100644 --- a/libqpdf/qpdf/QPDF_Name.hh +++ b/libqpdf/qpdf/QPDF_Name.hh @@ -1,9 +1,9 @@ #ifndef QPDF_NAME_HH #define QPDF_NAME_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Name: public QPDFObject +class QPDF_Name: public QPDFValue { public: virtual ~QPDF_Name() = default; @@ -11,8 +11,6 @@ class QPDF_Name: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; std::string getName() const; // Put # into strings with characters unsuitable for name token diff --git a/libqpdf/qpdf/QPDF_Null.hh b/libqpdf/qpdf/QPDF_Null.hh index 16833424..68973de9 100644 --- a/libqpdf/qpdf/QPDF_Null.hh +++ b/libqpdf/qpdf/QPDF_Null.hh @@ -1,9 +1,9 @@ #ifndef QPDF_NULL_HH #define QPDF_NULL_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Null: public QPDFObject +class QPDF_Null: public QPDFValue { public: virtual ~QPDF_Null() = default; @@ -11,11 +11,9 @@ class QPDF_Null: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; private: - QPDF_Null() = default; + QPDF_Null(); }; #endif // QPDF_NULL_HH diff --git a/libqpdf/qpdf/QPDF_Operator.hh b/libqpdf/qpdf/QPDF_Operator.hh index 1da43d72..767c0ba0 100644 --- a/libqpdf/qpdf/QPDF_Operator.hh +++ b/libqpdf/qpdf/QPDF_Operator.hh @@ -1,9 +1,9 @@ #ifndef QPDF_OPERATOR_HH #define QPDF_OPERATOR_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Operator: public QPDFObject +class QPDF_Operator: public QPDFValue { public: virtual ~QPDF_Operator() = default; @@ -11,8 +11,6 @@ class QPDF_Operator: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; std::string getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Real.hh b/libqpdf/qpdf/QPDF_Real.hh index f5ab4bd6..dc0f3ff8 100644 --- a/libqpdf/qpdf/QPDF_Real.hh +++ b/libqpdf/qpdf/QPDF_Real.hh @@ -1,9 +1,9 @@ #ifndef QPDF_REAL_HH #define QPDF_REAL_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Real: public QPDFObject +class QPDF_Real: public QPDFValue { public: virtual ~QPDF_Real() = default; @@ -13,8 +13,6 @@ class QPDF_Real: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; std::string getVal(); private: diff --git a/libqpdf/qpdf/QPDF_Reserved.hh b/libqpdf/qpdf/QPDF_Reserved.hh index 243a1728..f90242a9 100644 --- a/libqpdf/qpdf/QPDF_Reserved.hh +++ b/libqpdf/qpdf/QPDF_Reserved.hh @@ -1,9 +1,9 @@ #ifndef QPDF_RESERVED_HH #define QPDF_RESERVED_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> -class QPDF_Reserved: public QPDFObject +class QPDF_Reserved: public QPDFValue { public: virtual ~QPDF_Reserved() = default; @@ -11,11 +11,9 @@ class QPDF_Reserved: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; private: - QPDF_Reserved() = default; + QPDF_Reserved(); }; #endif // QPDF_RESERVED_HH diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh index 8980c751..3a16160e 100644 --- a/libqpdf/qpdf/QPDF_Stream.hh +++ b/libqpdf/qpdf/QPDF_Stream.hh @@ -3,9 +3,9 @@ #include <qpdf/Types.h> -#include <qpdf/QPDFObject.hh> #include <qpdf/QPDFObjectHandle.hh> #include <qpdf/QPDFStreamFilter.hh> +#include <qpdf/QPDFValue.hh> #include <functional> #include <memory> @@ -13,7 +13,7 @@ class Pipeline; class QPDF; -class QPDF_Stream: public QPDFObject +class QPDF_Stream: public QPDFValue { public: virtual ~QPDF_Stream() = default; @@ -26,8 +26,6 @@ class QPDF_Stream: public QPDFObject virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); virtual JSON getJSON(int json_version); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; virtual void setDescription(QPDF*, std::string const&); QPDFObjectHandle getDict() const; bool isDataModified() const; diff --git a/libqpdf/qpdf/QPDF_String.hh b/libqpdf/qpdf/QPDF_String.hh index b6d77637..a92427e3 100644 --- a/libqpdf/qpdf/QPDF_String.hh +++ b/libqpdf/qpdf/QPDF_String.hh @@ -1,11 +1,11 @@ #ifndef QPDF_STRING_HH #define QPDF_STRING_HH -#include <qpdf/QPDFObject.hh> +#include <qpdf/QPDFValue.hh> // QPDF_Strings may included embedded null characters. -class QPDF_String: public QPDFObject +class QPDF_String: public QPDFValue { friend class QPDFWriter; @@ -16,8 +16,6 @@ class QPDF_String: public QPDFObject create_utf16(std::string const& utf8_val); virtual std::shared_ptr<QPDFObject> shallowCopy(); virtual std::string unparse(); - virtual QPDFObject::object_type_e getTypeCode() const; - virtual char const* getTypeName() const; std::string unparse(bool force_binary); virtual JSON getJSON(int json_version); std::string getVal() const; diff --git a/libqpdf/qpdf/QPDF_Unresolved.hh b/libqpdf/qpdf/QPDF_Unresolved.hh new file mode 100644 index 00000000..efcf4e3d --- /dev/null +++ b/libqpdf/qpdf/QPDF_Unresolved.hh @@ -0,0 +1,19 @@ +#ifndef QPDF_UNRESOLVED_HH +#define QPDF_UNRESOLVED_HH + +#include <qpdf/QPDFValue.hh> + +class QPDF_Unresolved: public QPDFValue +{ + public: + virtual ~QPDF_Unresolved() = default; + static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen const& og); + virtual std::shared_ptr<QPDFObject> shallowCopy(); + virtual std::string unparse(); + virtual JSON getJSON(int json_version); + + private: + QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og); +}; + +#endif // QPDF_UNRESOLVED_HH |