diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 3c7b62f8..af454e75 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -43,8 +43,18 @@ class Pipeline; class QPDF; -class QPDF_Dictionary; class QPDF_Array; +class QPDF_Bool; +class QPDF_Dictionary; +class QPDF_InlineImage; +class QPDF_Integer; +class QPDF_Name; +class QPDF_Null; +class QPDF_Operator; +class QPDF_Real; +class QPDF_Reserved; +class QPDF_Stream; +class QPDF_String; class QPDFTokenizer; class QPDFExc; class Pl_QPDFTokenizer; @@ -1480,6 +1490,16 @@ class QPDFObjectHandle }; return o.obj; } + static QPDF_Array* + asArray(QPDFObjectHandle& oh) + { + return oh.asArray(); + } + static QPDF_Stream* + asStream(QPDFObjectHandle& oh) + { + return oh.asStream(); + } }; friend class ObjAccessor; @@ -1581,6 +1601,20 @@ class QPDFObjectHandle qpdf_offset_t offset, size_t length); + QPDF_Array* asArray(); + QPDF_Bool* asBool(); + QPDF_Dictionary* asDictionary(); + QPDF_InlineImage* asInlineImage(); + QPDF_Integer* asInteger(); + QPDF_Name* asName(); + QPDF_Null* asNull(); + QPDF_Operator* asOperator(); + QPDF_Real* asReal(); + QPDF_Reserved* asReserved(); + QPDF_Stream* asStream(); + QPDF_Stream* asStreamWithAssert(); + QPDF_String* asString(); + void typeWarning(char const* expected_type, std::string const& warning); void objectWarning(std::string const& warning); void assertType(char const* type_name, bool istype); @@ -1881,7 +1915,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) { // This is called during parsing on newly created direct objects, // so we can't call dereference() here. - if (this->obj.get()) { + if (initialized) { this->obj->setParsedOffset(offset); } } diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 191d98f3..22f62a8b 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -1420,8 +1420,7 @@ QPDF::fixDanglingReferences(bool force) to_check.push_back(iter.second); } } else if (obj.isArray()) { - QPDF_Array* arr = dynamic_cast( - QPDFObjectHandle::ObjAccessor::getObject(obj).get()); + auto arr = QPDFObjectHandle::ObjAccessor::asArray(obj); arr->addExplicitElementsToList(to_check); } for (auto sub: to_check) { @@ -2468,12 +2467,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( - 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"); } diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index f872e984..f60d131a 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -277,24 +277,91 @@ QPDFObjectHandle::getTypeName() return dereference() ? this->obj->getTypeName() : "uninitialized"; } -namespace +QPDF_Array* +QPDFObjectHandle::asArray() { - template - class QPDFObjectTypeAccessor - { - public: - static bool - check(std::shared_ptr const& o) - { - return (o && dynamic_cast(o.get())); - } - }; -} // namespace + return isArray() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Bool* +QPDFObjectHandle::asBool() +{ + return isBool() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Dictionary* +QPDFObjectHandle::asDictionary() +{ + return isDictionary() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_InlineImage* +QPDFObjectHandle::asInlineImage() +{ + return isInlineImage() ? dynamic_cast(obj.get()) + : nullptr; +} + +QPDF_Integer* +QPDFObjectHandle::asInteger() +{ + return isInteger() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Name* +QPDFObjectHandle::asName() +{ + return isName() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Null* +QPDFObjectHandle::asNull() +{ + return isNull() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Operator* +QPDFObjectHandle::asOperator() +{ + return isOperator() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Real* +QPDFObjectHandle::asReal() +{ + return isReal() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Reserved* +QPDFObjectHandle::asReserved() +{ + return isReserved() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Stream* +QPDFObjectHandle::asStream() +{ + return isStream() ? dynamic_cast(obj.get()) : nullptr; +} + +QPDF_Stream* +QPDFObjectHandle::asStreamWithAssert() +{ + auto stream = asStream(); + assertType("stream", stream); + return stream; +} + +QPDF_String* +QPDFObjectHandle::asString() +{ + return isString() ? dynamic_cast(obj.get()) : nullptr; +} bool QPDFObjectHandle::isBool() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_boolean); } bool @@ -303,26 +370,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::check(obj)); + initialized && (getObjectID() == 0) && + (obj->getTypeCode() == QPDFObject::ot_null)); } bool QPDFObjectHandle::isNull() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_null); } bool QPDFObjectHandle::isInteger() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_integer); } bool QPDFObjectHandle::isReal() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_real); } bool @@ -359,51 +426,49 @@ QPDFObjectHandle::getValueAsNumber(double& value) bool QPDFObjectHandle::isName() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_name); } bool QPDFObjectHandle::isString() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_string); } bool QPDFObjectHandle::isOperator() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_operator); } bool QPDFObjectHandle::isInlineImage() { - return dereference() && - QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_inlineimage); } bool QPDFObjectHandle::isArray() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_array); } bool QPDFObjectHandle::isDictionary() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_dictionary); } bool QPDFObjectHandle::isStream() { - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_stream); } bool QPDFObjectHandle::isReserved() { - // dereference will clear reserved if this has been replaced - return dereference() && QPDFObjectTypeAccessor::check(obj); + return dereference() && (obj->getTypeCode() == QPDFObject::ot_reserved); } bool @@ -441,8 +506,9 @@ QPDFObjectHandle::isStreamOfType( bool QPDFObjectHandle::getBoolValue() { - if (isBool()) { - return dynamic_cast(obj.get())->getVal(); + auto boolean = asBool(); + if (boolean) { + return boolean->getVal(); } else { typeWarning("boolean", "returning false"); QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); @@ -453,10 +519,11 @@ QPDFObjectHandle::getBoolValue() bool QPDFObjectHandle::getValueAsBool(bool& value) { - if (!isBool()) { + auto boolean = asBool(); + if (boolean == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = boolean->getVal(); return true; } @@ -465,8 +532,9 @@ QPDFObjectHandle::getValueAsBool(bool& value) long long QPDFObjectHandle::getIntValue() { - if (isInteger()) { - return dynamic_cast(obj.get())->getVal(); + auto integer = asInteger(); + if (integer) { + return integer->getVal(); } else { typeWarning("integer", "returning 0"); QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); @@ -477,10 +545,11 @@ QPDFObjectHandle::getIntValue() bool QPDFObjectHandle::getValueAsInt(long long& value) { - if (!isInteger()) { + auto integer = asInteger(); + if (integer == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = integer->getVal(); return true; } @@ -576,8 +645,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int& value) std::string QPDFObjectHandle::getRealValue() { - if (isReal()) { - return dynamic_cast(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"); @@ -588,10 +658,11 @@ QPDFObjectHandle::getRealValue() bool QPDFObjectHandle::getValueAsReal(std::string& value) { - if (!isReal()) { + auto real = asReal(); + if (real == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = real->getVal(); return true; } @@ -600,8 +671,9 @@ QPDFObjectHandle::getValueAsReal(std::string& value) std::string QPDFObjectHandle::getName() { - if (isName()) { - return dynamic_cast(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"); @@ -612,10 +684,11 @@ QPDFObjectHandle::getName() bool QPDFObjectHandle::getValueAsName(std::string& value) { - if (!isName()) { + auto name = asName(); + if (name == nullptr) { return false; } - value = dynamic_cast(obj.get())->getName(); + value = name->getName(); return true; } @@ -624,8 +697,9 @@ QPDFObjectHandle::getValueAsName(std::string& value) std::string QPDFObjectHandle::getStringValue() { - if (isString()) { - return dynamic_cast(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"); @@ -636,18 +710,20 @@ QPDFObjectHandle::getStringValue() bool QPDFObjectHandle::getValueAsString(std::string& value) { - if (!isString()) { + auto str = asString(); + if (str == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = str->getVal(); return true; } std::string QPDFObjectHandle::getUTF8Value() { - if (isString()) { - return dynamic_cast(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"); @@ -658,10 +734,11 @@ QPDFObjectHandle::getUTF8Value() bool QPDFObjectHandle::getValueAsUTF8(std::string& value) { - if (!isString()) { + auto str = asString(); + if (str == nullptr) { return false; } - value = dynamic_cast(obj.get())->getUTF8Val(); + value = str->getUTF8Val(); return true; } @@ -670,8 +747,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string& value) std::string QPDFObjectHandle::getOperatorValue() { - if (isOperator()) { - return dynamic_cast(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"); @@ -682,18 +760,20 @@ QPDFObjectHandle::getOperatorValue() bool QPDFObjectHandle::getValueAsOperator(std::string& value) { - if (!isOperator()) { + auto op = asOperator(); + if (op == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = op->getVal(); return true; } std::string QPDFObjectHandle::getInlineImageValue() { - if (isInlineImage()) { - return dynamic_cast(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"); @@ -704,10 +784,11 @@ QPDFObjectHandle::getInlineImageValue() bool QPDFObjectHandle::getValueAsInlineImage(std::string& value) { - if (!isInlineImage()) { + auto image = asInlineImage(); + if (image == nullptr) { return false; } - value = dynamic_cast(obj.get())->getVal(); + value = image->getVal(); return true; } @@ -722,8 +803,9 @@ QPDFObjectHandle::aitems() int QPDFObjectHandle::getArrayNItems() { - if (isArray()) { - return dynamic_cast(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"); @@ -735,11 +817,12 @@ QPDFObjectHandle QPDFObjectHandle::getArrayItem(int n) { QPDFObjectHandle result; - if (isArray() && (n < getArrayNItems()) && (n >= 0)) { - result = dynamic_cast(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 { @@ -748,7 +831,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"); @@ -760,14 +843,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; } } @@ -777,14 +858,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; } } @@ -796,13 +875,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), @@ -817,13 +897,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; } @@ -832,8 +913,9 @@ std::vector QPDFObjectHandle::getArrayAsVector() { std::vector result; - if (isArray()) { - dynamic_cast(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"); @@ -846,9 +928,10 @@ QPDFObjectHandle::getArrayAsVector() void QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) { - if (isArray()) { + auto array = asArray(); + if (array) { checkOwnership(item); - dynamic_cast(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"); @@ -858,11 +941,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) void QPDFObjectHandle::setArrayFromVector(std::vector const& items) { - if (isArray()) { + auto array = asArray(); + if (array) { for (auto const& item: items) { checkOwnership(item); } - dynamic_cast(obj.get())->setFromVector(items); + array->setFromVector(items); } else { typeWarning("array", "ignoring attempt to replace items"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); @@ -872,8 +956,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector const& items) void QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) { - if (isArray()) { - dynamic_cast(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"); @@ -890,9 +975,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(obj.get())->appendItem(item); + array->appendItem(item); } else { typeWarning("array", "ignoring attempt to append item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); @@ -909,10 +995,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const& item) void QPDFObjectHandle::eraseItem(int at) { - if (isArray() && (at < getArrayNItems()) && (at >= 0)) { - dynamic_cast(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 { @@ -926,8 +1013,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; @@ -944,8 +1032,9 @@ QPDFObjectHandle::ditems() bool QPDFObjectHandle::hasKey(std::string const& key) { - if (isDictionary()) { - return dynamic_cast(obj.get())->hasKey(key); + auto dict = asDictionary(); + if (dict) { + return dict->hasKey(key); } else { typeWarning( "dictionary", "returning false for a key containment request"); @@ -958,15 +1047,16 @@ QPDFObjectHandle QPDFObjectHandle::getKey(std::string const& key) { QPDFObjectHandle result; - if (isDictionary()) { - result = dynamic_cast(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 + @@ -986,8 +1076,9 @@ std::set QPDFObjectHandle::getKeys() { std::set result; - if (isDictionary()) { - result = dynamic_cast(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"); @@ -999,8 +1090,9 @@ std::map QPDFObjectHandle::getDictAsMap() { std::map result; - if (isDictionary()) { - result = dynamic_cast(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"); @@ -1191,9 +1283,10 @@ void QPDFObjectHandle::replaceKey( std::string const& key, QPDFObjectHandle const& value) { - if (isDictionary()) { + auto dict = asDictionary(); + if (dict) { checkOwnership(value); - dynamic_cast(obj.get())->replaceKey(key, value); + dict->replaceKey(key, value); } else { typeWarning("dictionary", "ignoring key replacement request"); QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); @@ -1220,8 +1313,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( void QPDFObjectHandle::removeKey(std::string const& key) { - if (isDictionary()) { - dynamic_cast(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"); @@ -1232,8 +1326,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; @@ -1250,50 +1345,43 @@ QPDFObjectHandle::replaceOrRemoveKey( QPDFObjectHandle QPDFObjectHandle::getDict() { - assertStream(); - return dynamic_cast(obj.get())->getDict(); + return asStreamWithAssert()->getDict(); } void QPDFObjectHandle::setFilterOnWrite(bool val) { - assertStream(); - dynamic_cast(obj.get())->setFilterOnWrite(val); + asStreamWithAssert()->setFilterOnWrite(val); } bool QPDFObjectHandle::getFilterOnWrite() { - assertStream(); - return dynamic_cast(obj.get())->getFilterOnWrite(); + return asStreamWithAssert()->getFilterOnWrite(); } bool QPDFObjectHandle::isDataModified() { - assertStream(); - return dynamic_cast(obj.get())->isDataModified(); + return asStreamWithAssert()->isDataModified(); } void QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict) { - assertStream(); - dynamic_cast(obj.get())->replaceDict(new_dict); + asStreamWithAssert()->replaceDict(new_dict); } std::shared_ptr QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) { - assertStream(); - return dynamic_cast(obj.get())->getStreamData(level); + return asStreamWithAssert()->getStreamData(level); } std::shared_ptr QPDFObjectHandle::getRawStreamData() { - assertStream(); - return dynamic_cast(obj.get())->getRawStreamData(); + return asStreamWithAssert()->getRawStreamData(); } bool @@ -1305,8 +1393,7 @@ QPDFObjectHandle::pipeStreamData( bool suppress_warnings, bool will_retry) { - assertStream(); - return dynamic_cast(obj.get())->pipeStreamData( + return asStreamWithAssert()->pipeStreamData( p, filtering_attempted, encode_flags, @@ -1323,9 +1410,8 @@ QPDFObjectHandle::pipeStreamData( bool suppress_warnings, bool will_retry) { - assertStream(); bool filtering_attempted; - dynamic_cast(obj.get())->pipeStreamData( + asStreamWithAssert()->pipeStreamData( p, &filtering_attempted, encode_flags, @@ -1359,9 +1445,7 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); - dynamic_cast(obj.get())->replaceStreamData( - data, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(data, filter, decode_parms); } void @@ -1370,14 +1454,12 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto b = std::make_shared(data.length()); unsigned char* bp = b->getBuffer(); if (bp) { memcpy(bp, data.c_str(), data.length()); } - dynamic_cast(obj.get())->replaceStreamData( - b, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(b, filter, decode_parms); } void @@ -1386,9 +1468,7 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); - dynamic_cast(obj.get())->replaceStreamData( - provider, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(provider, filter, decode_parms); } namespace @@ -1437,11 +1517,9 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto sdp = std::shared_ptr(new FunctionProvider(provider)); - dynamic_cast(obj.get())->replaceStreamData( - sdp, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); } void @@ -1450,11 +1528,9 @@ QPDFObjectHandle::replaceStreamData( QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms) { - assertStream(); auto sdp = std::shared_ptr(new FunctionProvider(provider)); - dynamic_cast(obj.get())->replaceStreamData( - sdp, filter, decode_parms); + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms); } std::map @@ -1469,10 +1545,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( { all_description = description; std::vector 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 { @@ -1649,8 +1726,9 @@ QPDFObjectHandle::unparseResolved() std::string QPDFObjectHandle::unparseBinary() { - if (this->isString()) { - return dynamic_cast(this->obj.get())->unparse(true); + auto str = asString(); + if (str) { + return str->unparse(true); } else { return unparse(); } @@ -1666,7 +1744,7 @@ 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( @@ -1675,7 +1753,7 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) throw std::logic_error( "QPDFObjectHandle: attempting to unparse a reserved object"); } else { - return this->obj->getJSON(json_version); + return obj->getJSON(json_version); } } @@ -1687,8 +1765,7 @@ QPDFObjectHandle::getStreamJSON( Pipeline* p, std::string const& data_filename) { - assertStream(); - return dynamic_cast(obj.get())->getStreamJSON( + return asStreamWithAssert()->getStreamJSON( json_version, json_data, decode_level, p, data_filename); } @@ -1908,8 +1985,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr filter) void QPDFObjectHandle::addTokenFilter(std::shared_ptr filter) { - assertStream(); - return dynamic_cast(obj.get())->addTokenFilter(filter); + return asStreamWithAssert()->addTokenFilter(filter); } QPDFObjectHandle @@ -1946,7 +2022,6 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og) QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid"); return newNull(); } - return QPDFObjectHandle(qpdf, og, QPDF_Unresolved::create()); } @@ -2119,8 +2194,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(result.obj.get()); + auto stream = result.asStream(); stream->setObjGen(result.getObjGen()); return result; } @@ -2248,9 +2322,10 @@ QPDFObjectHandle::copyObject( new_obj = obj->shallowCopy(); } else if (isArray()) { std::vector 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( @@ -2260,8 +2335,9 @@ QPDFObjectHandle::copyObject( new_obj = QPDF_Array::create(items); } else if (isDictionary()) { std::map 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( @@ -2309,7 +2385,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) void QPDFObjectHandle::assertInitialized() const { - if (!this->initialized) { + if (!initialized) { throw std::logic_error("operation attempted on uninitialized " "QPDFObjectHandle"); } @@ -2551,7 +2627,6 @@ QPDFObjectHandle::dereference() (getObjectID() && QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj))) { this->obj = QPDF::Resolver::resolve(this->qpdf, getObjGen()); - } return true; } diff --git a/libqpdf/QPDF_Reserved.cc b/libqpdf/QPDF_Reserved.cc index 5808a369..d5009674 100644 --- a/libqpdf/QPDF_Reserved.cc +++ b/libqpdf/QPDF_Reserved.cc @@ -17,14 +17,16 @@ 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(); }