In FUTURE make QPDFObjectHandle methods const where possible

This commit is contained in:
m-holger 2024-03-16 16:43:36 +00:00
parent 85c3955c9c
commit 3cd3c22df8
9 changed files with 589 additions and 165 deletions

View File

@ -775,16 +775,10 @@ class QPDF
friend class QPDF_Unresolved;
private:
static void
resolve(QPDF* qpdf, QPDFObjGen og)
{
qpdf->resolve(og);
}
static QPDFObject*
getResolved(QPDF* qpdf, QPDFObjGen og)
resolved(QPDF* qpdf, QPDFObjGen og)
{
qpdf->resolve(og);
return qpdf->m->obj_cache[og].object.get();
return qpdf->resolve(og);
}
};
@ -1035,7 +1029,7 @@ class QPDF
QPDFObjGen exp_og,
QPDFObjGen& og,
bool skip_cache_if_in_xref);
void resolve(QPDFObjGen og);
QPDFObject* resolve(QPDFObjGen og);
void resolveObjectsInStream(int obj_stream_number);
void stopOnError(std::string const& message);
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);

View File

@ -1367,12 +1367,12 @@ class QPDFObjectHandle
QPDF_Real* asReal() const;
QPDF_Reserved* asReserved() const;
QPDF_Stream* asStream() const;
QPDF_Stream* asStreamWithAssert();
QPDF_Stream* asStreamWithAssert() const;
QPDF_String* asString() const;
void typeWarning(char const* expected_type, std::string const& warning);
void objectWarning(std::string const& warning);
void assertType(char const* type_name, bool istype);
void typeWarning(char const* expected_type, std::string const& warning) const;
void objectWarning(std::string const& warning) const;
void assertType(char const* type_name, bool istype) const;
void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
void disconnect();
void setParsedOffset(qpdf_offset_t offset);

View File

@ -304,41 +304,41 @@ class QPDFObjectHandle
// other one changes color." This does not perform a structural comparison of the contents of
// the objects.
QPDF_DLL
bool isSameObjectAs(QPDFObjectHandle const&) const;
bool isSameObjectAs(QPDFObjectHandle const&) const noexcept;
// Return type code and type name of underlying object. These are useful for doing rapid type
// tests (like switch statements) or for testing and debugging.
QPDF_DLL
qpdf_object_type_e getTypeCode();
qpdf_object_type_e getTypeCode() const;
QPDF_DLL
char const* getTypeName();
// Exactly one of these will return true for any initialized object. Operator and InlineImage
// are only allowed in content streams.
QPDF_DLL
bool isBool();
bool isBool() const;
QPDF_DLL
bool isNull();
bool isNull() const;
QPDF_DLL
bool isInteger();
bool isInteger() const;
QPDF_DLL
bool isReal();
bool isReal() const;
QPDF_DLL
bool isName();
bool isName() const;
QPDF_DLL
bool isString();
bool isString() const;
QPDF_DLL
bool isOperator();
bool isOperator() const;
QPDF_DLL
bool isInlineImage();
bool isInlineImage() const;
QPDF_DLL
bool isArray();
bool isArray() const;
QPDF_DLL
bool isDictionary();
bool isDictionary() const;
QPDF_DLL
bool isStream();
bool isStream() const;
QPDF_DLL
bool isReserved();
bool isReserved() const;
// True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
// for internal use, but it can be used as an efficient way to check for nulls that are not
@ -353,23 +353,23 @@ class QPDFObjectHandle
// This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
// such an object will throw a logic_error.
QPDF_DLL
bool isDestroyed();
bool isDestroyed() const;
// True for everything except array, dictionary, stream, word, and inline image.
QPDF_DLL
bool isScalar();
bool isScalar() const;
// True if the object is a name object representing the provided name.
QPDF_DLL
bool isNameAndEquals(std::string const& name);
bool isNameAndEquals(std::string const& name) const;
// True if the object is a dictionary of the specified type and subtype, if any.
QPDF_DLL
bool isDictionaryOfType(std::string const& type, std::string const& subtype = "");
bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
// True if the object is a stream of the specified type and subtype, if any.
QPDF_DLL
bool isStreamOfType(std::string const& type, std::string const& subtype = "");
bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
// Public factory methods
@ -414,7 +414,7 @@ class QPDFObjectHandle
// object was created without parsing. If the object is in a stream, the offset is from the
// beginning of the stream. Otherwise, the offset is from the beginning of the file.
QPDF_DLL
qpdf_offset_t getParsedOffset();
qpdf_offset_t getParsedOffset() const;
// Older method: stream_or_array should be the value of /Contents from a page object. It's more
// convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
@ -586,7 +586,7 @@ class QPDFObjectHandle
QPDF_DLL
void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
QPDF_DLL
bool hasObjectDescription();
bool hasObjectDescription() const;
// Accessor methods
//
@ -636,57 +636,57 @@ class QPDFObjectHandle
// Methods for bool objects
QPDF_DLL
bool getBoolValue();
bool getBoolValue() const;
QPDF_DLL
bool getValueAsBool(bool&);
bool getValueAsBool(bool&) const;
// Methods for integer objects. Note: if an integer value is too big (too far away from zero in
// either direction) to fit in the requested return type, the maximum or minimum value for that
// return type may be returned. For example, on a system with 32-bit int, a numeric object with
// a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
QPDF_DLL
long long getIntValue();
long long getIntValue() const;
QPDF_DLL
bool getValueAsInt(long long&);
bool getValueAsInt(long long&) const;
QPDF_DLL
int getIntValueAsInt();
int getIntValueAsInt() const;
QPDF_DLL
bool getValueAsInt(int&);
bool getValueAsInt(int&) const;
QPDF_DLL
unsigned long long getUIntValue();
unsigned long long getUIntValue() const;
QPDF_DLL
bool getValueAsUInt(unsigned long long&);
bool getValueAsUInt(unsigned long long&) const;
QPDF_DLL
unsigned int getUIntValueAsUInt();
unsigned int getUIntValueAsUInt() const;
QPDF_DLL
bool getValueAsUInt(unsigned int&);
bool getValueAsUInt(unsigned int&) const;
// Methods for real objects
QPDF_DLL
std::string getRealValue();
std::string getRealValue() const;
QPDF_DLL
bool getValueAsReal(std::string&);
bool getValueAsReal(std::string&) const;
// Methods that work for both integer and real objects
QPDF_DLL
bool isNumber();
bool isNumber() const;
QPDF_DLL
double getNumericValue();
double getNumericValue() const;
QPDF_DLL
bool getValueAsNumber(double&);
bool getValueAsNumber(double&) const;
// Methods for name objects. The returned name value is in qpdf's canonical form with all
// escaping resolved. See comments for newName() for details.
QPDF_DLL
std::string getName();
std::string getName() const;
QPDF_DLL
bool getValueAsName(std::string&);
bool getValueAsName(std::string&) const;
// Methods for string objects
QPDF_DLL
std::string getStringValue();
std::string getStringValue() const;
QPDF_DLL
bool getValueAsString(std::string&);
bool getValueAsString(std::string&) const;
// If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
// it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
@ -694,19 +694,19 @@ class QPDFObjectHandle
// to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
// unmapped.
QPDF_DLL
std::string getUTF8Value();
std::string getUTF8Value() const;
QPDF_DLL
bool getValueAsUTF8(std::string&);
bool getValueAsUTF8(std::string&) const;
// Methods for content stream objects
QPDF_DLL
std::string getOperatorValue();
std::string getOperatorValue() const;
QPDF_DLL
bool getValueAsOperator(std::string&);
bool getValueAsOperator(std::string&) const;
QPDF_DLL
std::string getInlineImageValue();
std::string getInlineImageValue() const;
QPDF_DLL
bool getValueAsInlineImage(std::string&);
bool getValueAsInlineImage(std::string&) const;
// Methods for array objects; see also name and array objects.
@ -721,26 +721,26 @@ class QPDFObjectHandle
QPDFArrayItems aitems();
QPDF_DLL
int getArrayNItems();
int getArrayNItems() const;
QPDF_DLL
QPDFObjectHandle getArrayItem(int n);
QPDFObjectHandle getArrayItem(int n) const;
// Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
// getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
// nulls.
QPDF_DLL
std::vector<QPDFObjectHandle> getArrayAsVector();
std::vector<QPDFObjectHandle> getArrayAsVector() const;
QPDF_DLL
bool isRectangle();
bool isRectangle() const;
// If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
// rectangle [0, 0, 0, 0]
QPDF_DLL
Rectangle getArrayAsRectangle();
Rectangle getArrayAsRectangle() const;
QPDF_DLL
bool isMatrix();
bool isMatrix() const;
// If the array is an array of six numeric values, return as a matrix. Otherwise, return the
// matrix [1, 0, 0, 1, 0, 0]
QPDF_DLL
Matrix getArrayAsMatrix();
Matrix getArrayAsMatrix() const;
// Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
// canonical name strings starting with a leading slash and not containing any PDF syntax
@ -760,27 +760,27 @@ class QPDFObjectHandle
// Return true if key is present. Keys with null values are treated as if they are not present.
// This is as per the PDF spec.
QPDF_DLL
bool hasKey(std::string const&);
bool hasKey(std::string const&) const;
// Return the value for the key. If the key is not present, null is returned.
QPDF_DLL
QPDFObjectHandle getKey(std::string const&);
QPDFObjectHandle getKey(std::string const&) const;
// If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
// lower-level dictionaries, as in
// auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
QPDF_DLL
QPDFObjectHandle getKeyIfDict(std::string const&);
QPDFObjectHandle getKeyIfDict(std::string const&) const;
// Return all keys. Keys with null values are treated as if they are not present. This is as
// per the PDF spec.
QPDF_DLL
std::set<std::string> getKeys();
std::set<std::string> getKeys() const;
// Return dictionary as a map. Entries with null values are included.
QPDF_DLL
std::map<std::string, QPDFObjectHandle> getDictAsMap();
std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
// Methods for name and array objects. The name value is in qpdf's canonical form with all
// escaping resolved. See comments for newName() for details.
QPDF_DLL
bool isOrHasName(std::string const&);
bool isOrHasName(std::string const&) const;
// Make all resources in a resource dictionary indirect. This just goes through all entries of
// top-level subdictionaries and converts any direct objects to indirect objects. This can be
@ -830,7 +830,7 @@ class QPDFObjectHandle
// method returns a set of all the keys in all top-level subdictionaries. For resources
// dictionaries, this is the collection of names that may be referenced in the content stream.
QPDF_DLL
std::set<std::string> getResourceNames();
std::set<std::string> getResourceNames() const;
// Find a unique name within a resource dictionary starting with a given prefix. This method
// works by appending a number to the given prefix. It searches starting with min_suffix and
@ -845,7 +845,7 @@ class QPDFObjectHandle
std::string getUniqueResourceName(
std::string const& prefix,
int& min_suffix,
std::set<std::string>* resource_names = nullptr);
std::set<std::string>* resource_names = nullptr) const;
// A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
// object. Indirect objects always have an owning QPDF. Direct objects that are read from the
@ -965,7 +965,7 @@ class QPDFObjectHandle
// Methods for stream objects
QPDF_DLL
QPDFObjectHandle getDict();
QPDFObjectHandle getDict() const;
// By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
// level, whether compression is enabled, and its ability to filter. Passing false will prevent
@ -1154,12 +1154,12 @@ class QPDFObjectHandle
inline int getGeneration() const;
QPDF_DLL
std::string unparse();
std::string unparse() const;
QPDF_DLL
std::string unparseResolved();
std::string unparseResolved() const;
// For strings only, force binary representation. Otherwise, same as unparse.
QPDF_DLL
std::string unparseBinary();
std::string unparseBinary() const;
// Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
// JSON version. The JSON is generated as follows:
@ -1193,19 +1193,19 @@ class QPDFObjectHandle
// the object. The effect of dereference_indirect applies only to this object. It is not
// recursive.
QPDF_DLL
JSON getJSON(int json_version, bool dereference_indirect = false);
JSON getJSON(int json_version, bool dereference_indirect = false) const;
// Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
// than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
// documentation for getJSON and JSON::write for further detail.
QPDF_DLL
void
writeJSON(int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0);
void writeJSON(
int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
// Deprecated version uses v1 for backward compatibility.
// ABI: remove for qpdf 12
[[deprecated("Use getJSON(int version)")]] QPDF_DLL JSON
getJSON(bool dereference_indirect = false);
getJSON(bool dereference_indirect = false) const;
// This method can be called on a stream to get a more extended JSON representation of the
// stream that includes the stream's data. The JSON object returned is always a dictionary whose
@ -1258,7 +1258,7 @@ class QPDFObjectHandle
// normally from the file have descriptions. See comments on setObjectDescription for additional
// details.
QPDF_DLL
void warnIfPossible(std::string const& warning);
void warnIfPossible(std::string const& warning) const;
// Provide access to specific classes for recursive disconnected().
class DisconnectAccess
@ -1281,55 +1281,55 @@ class QPDFObjectHandle
void assertInitialized() const;
QPDF_DLL
void assertNull();
void assertNull() const;
QPDF_DLL
void assertBool();
void assertBool() const;
QPDF_DLL
void assertInteger();
void assertInteger() const;
QPDF_DLL
void assertReal();
void assertReal() const;
QPDF_DLL
void assertName();
void assertName() const;
QPDF_DLL
void assertString();
void assertString() const;
QPDF_DLL
void assertOperator();
void assertOperator() const;
QPDF_DLL
void assertInlineImage();
void assertInlineImage() const;
QPDF_DLL
void assertArray();
void assertArray() const;
QPDF_DLL
void assertDictionary();
void assertDictionary() const;
QPDF_DLL
void assertStream();
void assertStream() const;
QPDF_DLL
void assertReserved();
void assertReserved() const;
QPDF_DLL
void assertIndirect();
void assertIndirect() const;
QPDF_DLL
void assertScalar();
void assertScalar() const;
QPDF_DLL
void assertNumber();
void assertNumber() const;
// The isPageObject method checks the /Type key of the object. This is not completely reliable
// as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
// slightly more accepting but may still return false here when treating the object as a page
// would work. Use this sparingly.
QPDF_DLL
bool isPageObject();
bool isPageObject() const;
QPDF_DLL
bool isPagesObject();
bool isPagesObject() const;
QPDF_DLL
void assertPageObject();
void assertPageObject() const;
QPDF_DLL
bool isFormXObject();
bool isFormXObject() const;
// Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
// images.
QPDF_DLL
bool isImage(bool exclude_imagemask = true);
bool isImage(bool exclude_imagemask = true) const;
// The following methods do not form part of the public API and are for internal use only.
@ -1358,7 +1358,7 @@ class QPDFObjectHandle
return obj.get();
}
void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false);
void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
private:
QPDF_Array* asArray() const;
@ -1372,12 +1372,12 @@ class QPDFObjectHandle
QPDF_Real* asReal() const;
QPDF_Reserved* asReserved() const;
QPDF_Stream* asStream() const;
QPDF_Stream* asStreamWithAssert();
QPDF_Stream* asStreamWithAssert() const;
QPDF_String* asString() const;
void typeWarning(char const* expected_type, std::string const& warning);
void objectWarning(std::string const& warning);
void assertType(char const* type_name, bool istype);
void typeWarning(char const* expected_type, std::string const& warning) const;
void objectWarning(std::string const& warning) const;
void assertType(char const* type_name, bool istype) const;
void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
void disconnect();
void setParsedOffset(qpdf_offset_t offset);

View File

@ -1696,11 +1696,11 @@ QPDF::readObjectAtOffset(
return oh;
}
void
QPDFObject*
QPDF::resolve(QPDFObjGen og)
{
if (!isUnresolved(og)) {
return;
return m->obj_cache[og].object.get();
}
if (m->resolving.count(og)) {
@ -1709,7 +1709,7 @@ QPDF::resolve(QPDFObjGen og)
QTC::TC("qpdf", "QPDF recursion loop in resolve");
warn(damagedPDF("", "loop detected resolving object " + og.unparse(' ')));
updateCache(og, QPDF_Null::create(), -1, -1);
return;
return m->obj_cache[og].object.get();
}
ResolveRecorder rr(this, og);
@ -1750,6 +1750,7 @@ QPDF::resolve(QPDFObjGen og)
auto result(m->obj_cache[og].object);
result->setDefaultDescription(this, og);
return result.get();
}
void

View File

@ -3,13 +3,6 @@
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_Destroyed.hh>
void
QPDFObject::doResolve()
{
auto og = value->og;
QPDF::Resolver::resolve(value->qpdf, og);
}
void
QPDFObject::destroy()
{

File diff suppressed because it is too large Load Diff

View File

@ -130,8 +130,7 @@ QPDF_Array::unparse()
for (int j = next; j < key; ++j) {
result += "null ";
}
item.second->resolve();
auto og = item.second->getObjGen();
auto og = item.second->resolved_object()->getObjGen();
result += og.isIndirect() ? og.unparse(' ') + " R " : item.second->unparse() + " ";
next = ++key;
}
@ -140,8 +139,7 @@ QPDF_Array::unparse()
}
} else {
for (auto const& item: elements) {
item->resolve();
auto og = item->getObjGen();
auto og = item->resolved_object()->getObjGen();
result += og.isIndirect() ? og.unparse(' ') + " R " : item->unparse() + " ";
}
}

View File

@ -17,23 +17,23 @@ QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og)
std::shared_ptr<QPDFObject>
QPDF_Unresolved::copy(bool shallow)
{
return QPDF::Resolver::getResolved(qpdf, og)->copy(shallow);
return QPDF::Resolver::resolved(qpdf, og)->copy(shallow);
}
std::string
QPDF_Unresolved::unparse()
{
return QPDF::Resolver::getResolved(qpdf, og)->unparse();
return QPDF::Resolver::resolved(qpdf, og)->unparse();
}
void
QPDF_Unresolved::writeJSON(int json_version, JSON::Writer& p)
{
QPDF::Resolver::getResolved(qpdf, og)->writeJSON(json_version, p);
QPDF::Resolver::resolved(qpdf, og)->writeJSON(json_version, p);
}
std::string
QPDF_Unresolved::getStringValue() const
{
return QPDF::Resolver::getResolved(qpdf, og)->getStringValue();
}
return QPDF::Resolver::resolved(qpdf, og)->getStringValue();
}

View File

@ -49,7 +49,7 @@ class QPDFObject
{
auto tc = value->type_code;
return tc == ::ot_unresolved
? QPDF::Resolver::getResolved(value->qpdf, value->og)->value->type_code
? QPDF::Resolver::resolved(value->qpdf, value->og)->value->type_code
: tc;
}
// Return a unique type code for the object
@ -165,21 +165,12 @@ class QPDFObject
{
return value->type_code == ::ot_unresolved;
}
void
resolve()
{
if (isUnresolved()) {
doResolve();
}
}
const QPDFObject*
resolved_object() const
{
return isUnresolved() ? QPDF::Resolver::getResolved(value->qpdf, value->og) : this;
return isUnresolved() ? QPDF::Resolver::resolved(value->qpdf, value->og) : this;
}
void doResolve();
template <typename T>
T*
as() const
@ -188,7 +179,7 @@ class QPDFObject
return result;
} else {
return isUnresolved()
? dynamic_cast<T*>(QPDF::Resolver::getResolved(value->qpdf, value->og)->value.get())
? dynamic_cast<T*>(QPDF::Resolver::resolved(value->qpdf, value->og)->value.get())
: nullptr;
}
}