diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index 2f0d629..4fb3ec3 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -252,16 +252,15 @@ QPDFFormFieldObjectHelper QPDFAcroFormDocumentHelper::getFieldForAnnotation(QPDFAnnotationObjectHelper h) { QPDFObjectHandle oh = h.getObjectHandle(); - QPDFFormFieldObjectHelper result(QPDFObjectHandle::newNull()); if (!oh.isDictionaryOfType("", "/Widget")) { - return result; + return Null::temp(); } analyze(); QPDFObjGen og(oh.getObjGen()); if (m->annotation_to_field.contains(og)) { - result = m->annotation_to_field[og]; + return m->annotation_to_field[og]; } - return result; + return Null::temp(); } void diff --git a/libqpdf/QPDFAnnotationObjectHelper.cc b/libqpdf/QPDFAnnotationObjectHelper.cc index ce2b12d..63e3628 100644 --- a/libqpdf/QPDFAnnotationObjectHelper.cc +++ b/libqpdf/QPDFAnnotationObjectHelper.cc @@ -56,20 +56,16 @@ QPDFAnnotationObjectHelper::getAppearanceStream(std::string const& which, std::s // appearance stream when /AP is a dictionary, but files have been seen in the wild // where Appearance State is `/N` and `/AP` is a stream. Therefore, if `which` points to // a stream, disregard state and just use the stream. See qpdf issue #949 for details. - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP stream"); return ap_sub; } - if (ap_sub.isDictionary() && (!desired_state.empty())) { - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP dictionary"); + if (ap_sub.isDictionary() && !desired_state.empty()) { QPDFObjectHandle ap_sub_val = ap_sub.getKey(desired_state); if (ap_sub_val.isStream()) { - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP sub stream"); return ap_sub_val; } } } - QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP null"); - return QPDFObjectHandle::newNull(); + return Null::temp(); } std::string diff --git a/libqpdf/QPDFEmbeddedFileDocumentHelper.cc b/libqpdf/QPDFEmbeddedFileDocumentHelper.cc index bdc86ad..d44c1ff 100644 --- a/libqpdf/QPDFEmbeddedFileDocumentHelper.cc +++ b/libqpdf/QPDFEmbeddedFileDocumentHelper.cc @@ -1,6 +1,7 @@ #include #include +#include #include // File attachments are stored in the /EmbeddedFiles (name tree) key of the /Names dictionary from @@ -143,11 +144,10 @@ QPDFEmbeddedFileDocumentHelper::removeEmbeddedFile(std::string const& name) if (iter == m->embedded_files->end()) { return false; } - auto oh = iter->second; - iter.remove(); - if (oh.isIndirect()) { - qpdf.replaceObject(oh.getObjGen(), QPDFObjectHandle::newNull()); + if (iter->second.indirect()) { + qpdf.replaceObject(iter->second, Null()); } + iter.remove(); return true; } diff --git a/libqpdf/QPDFFileSpecObjectHelper.cc b/libqpdf/QPDFFileSpecObjectHelper.cc index d92aac4..570b056 100644 --- a/libqpdf/QPDFFileSpecObjectHelper.cc +++ b/libqpdf/QPDFFileSpecObjectHelper.cc @@ -76,7 +76,7 @@ QPDFFileSpecObjectHelper::getEmbeddedFileStream(std::string const& key) } } } - return QPDFObjectHandle::newNull(); + return Null::temp(); } QPDFObjectHandle diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 0d820a6..2cafbab 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -25,6 +25,8 @@ using namespace std::literals; using namespace qpdf; +const Null Null::temp_; + BaseHandle:: operator QPDFObjGen() const { diff --git a/libqpdf/qpdf/QPDFObjectHandle_private.hh b/libqpdf/qpdf/QPDFObjectHandle_private.hh index cccbd7d..834b09c 100644 --- a/libqpdf/qpdf/QPDFObjectHandle_private.hh +++ b/libqpdf/qpdf/QPDFObjectHandle_private.hh @@ -468,6 +468,39 @@ namespace qpdf } }; + class Null final: public BaseHandle + { + public: + // Unlike other types, the Null default constructor creates a valid null object. + Null() : + BaseHandle(QPDFObject::create()) + { + } + + Null(Null const&) = default; + Null(Null&&) = default; + Null& operator=(Null const&) = default; + Null& operator=(Null&&) = default; + ~Null() = default; + + // For legacy support, return a Null object to be used as a temporary return value. + static QPDFObjectHandle + temp() + { + return temp_.oh(); + } + + // For legacy support, return an explicit temporary Null object if oh is null. + static QPDFObjectHandle + if_null(QPDFObjectHandle oh) + { + return oh ? std::move(oh) : Null::temp(); + } + + private: + static const Null temp_; + }; // class Null + class Stream final: public BaseHandle { public: diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 2c10208..8c9646e 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -181,10 +181,6 @@ QPDFFormFieldObjectHelper TU absent 0 QPDFFormFieldObjectHelper TM absent 0 QPDFFormFieldObjectHelper Q present 1 QPDFFormFieldObjectHelper DA present 1 -QPDFAnnotationObjectHelper AP stream 0 -QPDFAnnotationObjectHelper AP dictionary 0 -QPDFAnnotationObjectHelper AP sub stream 0 -QPDFAnnotationObjectHelper AP null 0 QPDFAcroFormDocumentHelper field found 1 QPDFAcroFormDocumentHelper annotation found 1 QPDFJob automatically set keep files open 1