aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJay Berkenbilt <jberkenbilt@users.noreply.github.com>2022-09-01 19:14:56 +0200
committerGitHub <noreply@github.com>2022-09-01 19:14:56 +0200
commitf8fd7d60e301b9b1bf4d705ce747e281c320487e (patch)
tree4aba6da08ae9d441ecf57eabefdc76185137d28d /include
parenta078202c1b5823f1c13a4c559619158054029e73 (diff)
parent805c1ad47968e33e1296af9a31492f6916ad9113 (diff)
downloadqpdf-f8fd7d60e301b9b1bf4d705ce747e281c320487e.tar.zst
Merge pull request #726 from m-holger/tidy3
Split QPDFObject into QPDFObject and QPDFValue
Diffstat (limited to 'include')
-rw-r--r--include/qpdf/Constants.h2
-rw-r--r--include/qpdf/QPDF.hh25
-rw-r--r--include/qpdf/QPDFObject.hh140
-rw-r--r--include/qpdf/QPDFObjectHandle.hh84
-rw-r--r--include/qpdf/QPDFValue.hh130
5 files changed, 320 insertions, 61 deletions
diff --git a/include/qpdf/Constants.h b/include/qpdf/Constants.h
index 5d2113bd..cf6bdaef 100644
--- a/include/qpdf/Constants.h
+++ b/include/qpdf/Constants.h
@@ -82,6 +82,8 @@ enum qpdf_object_type_e {
/* Additional object types that can occur in content streams */
ot_operator,
ot_inlineimage,
+ /* Object types internal to qpdf */
+ ot_unresolved,
/* NOTE: if adding to this list, update QPDFObject.hh */
};
diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh
index 12d41eff..bcd85cd2 100644
--- a/include/qpdf/QPDF.hh
+++ b/include/qpdf/QPDF.hh
@@ -843,19 +843,13 @@ class QPDF
// it can resolve indirect references.
class Resolver
{
- friend class QPDFObjectHandle;
+ friend class QPDFObject;
private:
- static std::shared_ptr<QPDFObject>
+ static void
resolve(QPDF* qpdf, QPDFObjGen const& og)
{
- return qpdf->resolve(og);
- }
- static bool
- objectChanged(
- QPDF* qpdf, QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph)
- {
- return qpdf->objectChanged(og, oph);
+ qpdf->resolve(og);
}
};
friend class Resolver;
@@ -1174,12 +1168,20 @@ class QPDF
std::string const& description,
QPDFObjGen const& exp_og,
QPDFObjGen& og);
- bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph);
- std::shared_ptr<QPDFObject> resolve(QPDFObjGen const& og);
+ void resolve(QPDFObjGen const& og);
void resolveObjectsInStream(int obj_stream_number);
void stopOnError(std::string const& message);
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
+ QPDFObjectHandle
+ newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
+ bool isCached(QPDFObjGen const& og);
+ bool isUnresolved(QPDFObjGen const& og);
+ void updateCache(
+ QPDFObjGen const& og,
+ std::shared_ptr<QPDFObject> const& object,
+ qpdf_offset_t end_before_space,
+ qpdf_offset_t end_after_space);
// Calls finish() on the pipeline when done but does not delete it
bool pipeStreamData(
@@ -1727,7 +1729,6 @@ class QPDF
bool in_parse;
bool parsed;
std::set<int> resolved_object_streams;
- bool ever_replaced_objects;
// Linearization data
qpdf_offset_t first_xref_item_offset; // actual value from file
diff --git a/include/qpdf/QPDFObject.hh b/include/qpdf/QPDFObject.hh
index eb7c4b90..e6d1d18b 100644
--- a/include/qpdf/QPDFObject.hh
+++ b/include/qpdf/QPDFObject.hh
@@ -25,6 +25,7 @@
#include <qpdf/Constants.h>
#include <qpdf/DLL.h>
#include <qpdf/JSON.hh>
+#include <qpdf/QPDFValue.hh>
#include <qpdf/Types.h>
#include <string>
@@ -34,9 +35,9 @@ class QPDFObjectHandle;
class QPDFObject
{
- public:
- QPDFObject();
+ friend class QPDFValue;
+ public:
// Objects derived from QPDFObject are accessible through
// QPDFObjectHandle. Each object returns a unique type code that
// has one of the valid qpdf_object_type_e values. As new object
@@ -61,18 +62,128 @@ class QPDFObject
static constexpr object_type_e ot_stream = ::ot_stream;
static constexpr object_type_e ot_operator = ::ot_operator;
static constexpr object_type_e ot_inlineimage = ::ot_inlineimage;
+ static constexpr object_type_e ot_unresolved = ::ot_unresolved;
+ QPDFObject() = default;
virtual ~QPDFObject() = default;
- virtual std::shared_ptr<QPDFObject> shallowCopy() = 0;
- virtual std::string unparse() = 0;
- virtual JSON getJSON(int json_version) = 0;
+
+ std::shared_ptr<QPDFObject>
+ shallowCopy()
+ {
+ return value->shallowCopy();
+ }
+ std::string
+ unparse()
+ {
+ return value->unparse();
+ }
+ JSON
+ getJSON(int json_version)
+ {
+ return value->getJSON(json_version);
+ }
// Return a unique type code for the object
- virtual object_type_e getTypeCode() const = 0;
+ object_type_e
+ getTypeCode() const
+ {
+ return value->type_code;
+ }
// Return a string literal that describes the type, useful for
// debugging and testing
- virtual char const* getTypeName() const = 0;
+ char const*
+ getTypeName() const
+ {
+ return value->type_name;
+ }
+ // Returns nullptr for direct objects
+ QPDF*
+ getQPDF() const
+ {
+ return value->qpdf;
+ }
+ QPDFObjGen
+ getObjGen() const
+ {
+ return value->og;
+ }
+
+ void
+ setDescription(QPDF* qpdf, std::string const& description)
+ {
+ return value->setDescription(qpdf, description);
+ }
+ bool
+ getDescription(QPDF*& qpdf, std::string& description)
+ {
+ return value->getDescription(qpdf, description);
+ }
+ bool
+ hasDescription()
+ {
+ return value->hasDescription();
+ }
+ void
+ setParsedOffset(qpdf_offset_t offset)
+ {
+ value->setParsedOffset(offset);
+ }
+ qpdf_offset_t
+ getParsedOffset()
+ {
+ return value->getParsedOffset();
+ }
+ void
+ assign(std::shared_ptr<QPDFObject> o)
+ {
+ value = o->value;
+ }
+ void
+ swapWith(std::shared_ptr<QPDFObject> o)
+ {
+ auto v = value;
+ value = o->value;
+ o->value = v;
+ auto og = value->og;
+ value->og = o->value->og;
+ o->value->og = og;
+ }
+
+ // The following two methods are for use by class QPDF only
+ void
+ setObjGen(QPDF* qpdf, QPDFObjGen const& og)
+ {
+ value->qpdf = qpdf;
+ value->og = og;
+ }
+ void
+ resetObjGen()
+ {
+ value->qpdf = nullptr;
+ value->og = QPDFObjGen();
+ }
+
+ bool
+ isUnresolved() const
+ {
+ return value->type_code == ::ot_unresolved;
+ }
+ void
+ resolve()
+ {
+ if (isUnresolved()) {
+ doResolve();
+ }
+ }
+ void doResolve();
+
+ template <typename T>
+ T*
+ as()
+ {
+ return dynamic_cast<T*>(value.get());
+ }
// Accessor to give specific access to non-public methods
class ObjAccessor
@@ -89,29 +200,20 @@ class QPDFObject
}
}
};
- friend class ObjAccessor;
- virtual void setDescription(QPDF*, std::string const&);
- bool getDescription(QPDF*&, std::string&);
- bool hasDescription();
-
- void setParsedOffset(qpdf_offset_t offset);
- qpdf_offset_t getParsedOffset();
+ friend class ObjAccessor;
protected:
virtual void
releaseResolved()
{
+ value->releaseResolved();
}
- static std::shared_ptr<QPDFObject> do_create(QPDFObject*);
private:
QPDFObject(QPDFObject const&) = delete;
QPDFObject& operator=(QPDFObject const&) = delete;
-
- QPDF* owning_qpdf;
- std::string object_description;
- qpdf_offset_t parsed_offset;
+ std::shared_ptr<QPDFValue> value;
};
#endif // QPDFOBJECT_HH
diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh
index c1bed81f..16e8dc8b 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;
@@ -316,7 +326,7 @@ class QPDFObjectHandle
};
QPDF_DLL
- QPDFObjectHandle();
+ QPDFObjectHandle() = default;
QPDF_DLL
QPDFObjectHandle(QPDFObjectHandle const&) = default;
QPDF_DLL
@@ -963,8 +973,8 @@ class QPDFObjectHandle
// null for a direct object if allow_nullptr is set to true or
// throws a runtime error otherwise.
QPDF_DLL
- inline QPDF*
- getOwningQPDF(bool allow_nullptr = true, std::string const& error_msg = "");
+ inline QPDF* getOwningQPDF(
+ bool allow_nullptr = true, std::string const& error_msg = "") const;
// Create a shallow copy of an object as a direct object, but do not
// traverse across indirect object boundaries. That means that,
@@ -1443,9 +1453,9 @@ class QPDFObjectHandle
private:
static QPDFObjectHandle
- newIndirect(QPDF* qpdf, QPDFObjGen const& og)
+ newIndirect(std::shared_ptr<QPDFObject> const& obj)
{
- return QPDFObjectHandle::newIndirect(qpdf, og);
+ return QPDFObjectHandle(obj);
}
static QPDFObjectHandle
newStream(
@@ -1458,12 +1468,6 @@ class QPDFObjectHandle
return QPDFObjectHandle::newStream(
qpdf, og, stream_dict, offset, length);
}
- // Reserve an object with a specific ID
- static QPDFObjectHandle
- makeReserved()
- {
- return QPDFObjectHandle::makeReserved();
- }
};
friend class Factory;
@@ -1483,6 +1487,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;
@@ -1563,18 +1577,32 @@ class QPDFObjectHandle
bool isImage(bool exclude_imagemask = true);
private:
- QPDFObjectHandle(QPDF*, QPDFObjGen const& og);
- QPDFObjectHandle(std::shared_ptr<QPDFObject> const&);
+ QPDFObjectHandle(std::shared_ptr<QPDFObject> const& obj) :
+ obj(obj)
+ {
+ }
// Private object factory methods
- static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og);
static QPDFObjectHandle newStream(
QPDF* qpdf,
QPDFObjGen const& og,
QPDFObjectHandle stream_dict,
qpdf_offset_t offset,
size_t length);
- static QPDFObjectHandle makeReserved();
+
+ 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);
@@ -1601,15 +1629,10 @@ class QPDFObjectHandle
static void warn(QPDF*, QPDFExc const&);
void checkOwnership(QPDFObjectHandle const&) const;
- bool initialized;
-
// Moving members of QPDFObjectHandle into a smart pointer incurs
// a substantial performance penalty since QPDFObjectHandle
// objects are copied around so frequently.
- QPDF* qpdf;
- QPDFObjGen og;
std::shared_ptr<QPDFObject> obj;
- bool reserved;
};
#ifndef QPDF_NO_QPDF_STRING
@@ -1832,44 +1855,45 @@ class QPDFObjectHandle::QPDFArrayItems
inline QPDFObjGen
QPDFObjectHandle::getObjGen() const
{
- return og;
+ return isInitialized() ? obj->getObjGen() : QPDFObjGen();
}
inline int
QPDFObjectHandle::getObjectID() const
{
- return og.getObj();
+ return getObjGen().getObj();
}
inline int
QPDFObjectHandle::getGeneration() const
{
- return og.getGen();
+ return getObjGen().getGen();
}
inline bool
QPDFObjectHandle::isIndirect() const
{
- return initialized && (getObjectID() != 0);
+ return (obj != nullptr) && (getObjectID() != 0);
}
inline bool
QPDFObjectHandle::isInitialized() const
{
- return initialized;
+ return obj != nullptr;
}
// Indirect object accessors
inline QPDF*
QPDFObjectHandle::getOwningQPDF(
- bool allow_nullptr, std::string const& error_msg)
+ bool allow_nullptr, std::string const& error_msg) const
{
// Will be null for direct objects
- if (!allow_nullptr && (this->qpdf == nullptr)) {
+ auto result = isInitialized() ? this->obj->getQPDF() : nullptr;
+ if (!allow_nullptr && (result == nullptr)) {
throw std::runtime_error(
error_msg == "" ? "attempt to use a null qpdf object" : error_msg);
}
- return this->qpdf;
+ return result;
}
inline void
@@ -1877,7 +1901,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 (isInitialized()) {
this->obj->setParsedOffset(offset);
}
}
diff --git a/include/qpdf/QPDFValue.hh b/include/qpdf/QPDFValue.hh
new file mode 100644
index 00000000..8b4f53b5
--- /dev/null
+++ b/include/qpdf/QPDFValue.hh
@@ -0,0 +1,130 @@
+// Copyright (c) 2005-2022 Jay Berkenbilt
+//
+// This file is part of qpdf.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Versions of qpdf prior to version 7 were released under the terms
+// of version 2.0 of the Artistic License. At your option, you may
+// continue to consider qpdf to be licensed under those terms. Please
+// see the manual for additional information.
+
+#ifndef QPDFVALUE_HH
+#define QPDFVALUE_HH
+
+#include <qpdf/Constants.h>
+#include <qpdf/DLL.h>
+#include <qpdf/JSON.hh>
+#include <qpdf/QPDFObjGen.hh>
+#include <qpdf/Types.h>
+
+#include <string>
+
+class QPDF;
+class QPDFObjectHandle;
+class QPDFObject;
+
+class QPDFValue
+{
+ friend class QPDFObject;
+
+ public:
+ virtual ~QPDFValue() = default;
+
+ virtual std::shared_ptr<QPDFObject> shallowCopy() = 0;
+ virtual std::string unparse() = 0;
+ virtual JSON getJSON(int json_version) = 0;
+ virtual void
+ setDescription(QPDF* qpdf, std::string const& description)
+ {
+ owning_qpdf = qpdf;
+ object_description = description;
+ }
+ bool
+ getDescription(QPDF*& qpdf, std::string& description)
+ {
+ qpdf = owning_qpdf;
+ description = object_description;
+ return owning_qpdf != nullptr;
+ }
+ bool
+ hasDescription()
+ {
+ return owning_qpdf != nullptr;
+ }
+ void
+ setParsedOffset(qpdf_offset_t offset)
+ {
+ if (parsed_offset < 0) {
+ parsed_offset = offset;
+ }
+ }
+ qpdf_offset_t
+ getParsedOffset()
+ {
+ return parsed_offset;
+ }
+ QPDF*
+ getQPDF()
+ {
+ return qpdf;
+ }
+ QPDFObjGen
+ getObjGen()
+ {
+ return og;
+ }
+
+ protected:
+ QPDFValue() :
+ type_code(::ot_uninitialized),
+ type_name("uninitialized")
+ {
+ }
+ QPDFValue(qpdf_object_type_e type_code, char const* type_name) :
+ type_code(type_code),
+ type_name(type_name)
+ {
+ }
+ QPDFValue(
+ qpdf_object_type_e type_code,
+ char const* type_name,
+ QPDF* qpdf,
+ QPDFObjGen const& og) :
+ type_code(type_code),
+ type_name(type_name),
+ qpdf(qpdf),
+ og(og)
+ {
+ }
+ virtual void
+ releaseResolved()
+ {
+ }
+ static std::shared_ptr<QPDFObject> do_create(QPDFValue*);
+
+ private:
+ QPDFValue(QPDFValue const&) = delete;
+ QPDFValue& operator=(QPDFValue const&) = delete;
+ QPDF* owning_qpdf{nullptr};
+ std::string object_description;
+ qpdf_offset_t parsed_offset{-1};
+ const qpdf_object_type_e type_code;
+ char const* type_name;
+
+ protected:
+ QPDF* qpdf{nullptr};
+ QPDFObjGen og;
+};
+
+#endif // QPDFVALUE_HH