aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/qpdf/BufferInputSource.hh25
-rw-r--r--include/qpdf/ClosedFileInputSource.hh21
-rw-r--r--include/qpdf/Constants.h2
-rw-r--r--include/qpdf/FileInputSource.hh21
-rw-r--r--include/qpdf/InputSource.hh68
-rw-r--r--include/qpdf/QPDF.hh39
-rw-r--r--include/qpdf/QPDFJob.hh1
-rw-r--r--include/qpdf/QPDFNameTreeObjectHelper.hh8
-rw-r--r--include/qpdf/QPDFNumberTreeObjectHelper.hh8
-rw-r--r--include/qpdf/QPDFObject.hh140
-rw-r--r--include/qpdf/QPDFObjectHandle.hh160
-rw-r--r--include/qpdf/QPDFTokenizer.hh94
-rw-r--r--include/qpdf/QPDFValue.hh130
-rw-r--r--include/qpdf/QTC.hh16
-rw-r--r--include/qpdf/QUtil.hh67
-rw-r--r--include/qpdf/auto_job_c_main.hh1
16 files changed, 612 insertions, 189 deletions
diff --git a/include/qpdf/BufferInputSource.hh b/include/qpdf/BufferInputSource.hh
index b965704f..1a93815b 100644
--- a/include/qpdf/BufferInputSource.hh
+++ b/include/qpdf/BufferInputSource.hh
@@ -54,26 +54,11 @@ class QPDF_DLL_CLASS BufferInputSource: public InputSource
virtual void unreadCh(char ch);
private:
- class QPDF_DLL_PRIVATE Members
- {
- friend class BufferInputSource;
-
- public:
- QPDF_DLL
- ~Members() = default;
-
- private:
- Members(bool own_memory, std::string const& description, Buffer* buf);
- Members(Members const&) = delete;
-
- bool own_memory;
- std::string description;
- Buffer* buf;
- qpdf_offset_t cur_offset;
- qpdf_offset_t max_offset;
- };
-
- std::shared_ptr<Members> m;
+ bool own_memory;
+ std::string description;
+ Buffer* buf;
+ qpdf_offset_t cur_offset;
+ qpdf_offset_t max_offset;
};
#endif // QPDF_BUFFERINPUTSOURCE_HH
diff --git a/include/qpdf/ClosedFileInputSource.hh b/include/qpdf/ClosedFileInputSource.hh
index c72a1df8..b23c2767 100644
--- a/include/qpdf/ClosedFileInputSource.hh
+++ b/include/qpdf/ClosedFileInputSource.hh
@@ -73,23 +73,10 @@ class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource
QPDF_DLL_PRIVATE
void after();
- class QPDF_DLL_PRIVATE Members
- {
- friend class ClosedFileInputSource;
-
- public:
- QPDF_DLL
- ~Members() = default;
-
- private:
- Members(char const* filename);
-
- std::string filename;
- qpdf_offset_t offset;
- std::shared_ptr<FileInputSource> fis;
- bool stay_open;
- };
- std::shared_ptr<Members> m;
+ std::string filename;
+ qpdf_offset_t offset;
+ std::shared_ptr<FileInputSource> fis;
+ bool stay_open;
};
#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH
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/FileInputSource.hh b/include/qpdf/FileInputSource.hh
index f1e7edf4..9e0d57fb 100644
--- a/include/qpdf/FileInputSource.hh
+++ b/include/qpdf/FileInputSource.hh
@@ -58,24 +58,9 @@ class QPDF_DLL_CLASS FileInputSource: public InputSource
FileInputSource(FileInputSource const&) = delete;
FileInputSource& operator=(FileInputSource const&) = delete;
- class QPDF_DLL_PRIVATE Members
- {
- friend class FileInputSource;
-
- public:
- QPDF_DLL
- ~Members();
-
- private:
- Members(bool close_file);
- Members(Members const&) = delete;
-
- bool close_file;
- std::string filename;
- FILE* file;
- };
-
- std::shared_ptr<Members> m;
+ bool close_file;
+ std::string filename;
+ FILE* file;
};
#endif // QPDF_FILEINPUTSOURCE_HH
diff --git a/include/qpdf/InputSource.hh b/include/qpdf/InputSource.hh
index 9feb8ec3..e9d99cdb 100644
--- a/include/qpdf/InputSource.hh
+++ b/include/qpdf/InputSource.hh
@@ -93,6 +93,12 @@ class QPDF_DLL_CLASS InputSource
// efficient.
virtual void unreadCh(char ch) = 0;
+ // The following methods are for use by QPDFTokenizer
+ inline qpdf_offset_t fastTell();
+ inline bool fastRead(char&);
+ inline void fastUnread(bool);
+ inline void loadBuffer();
+
protected:
qpdf_offset_t last_offset;
@@ -111,6 +117,68 @@ class QPDF_DLL_CLASS InputSource
};
std::shared_ptr<Members> m;
+
+ // State for fast... methods
+ static const qpdf_offset_t buf_size = 128;
+ char buffer[buf_size];
+ qpdf_offset_t buf_len = 0;
+ qpdf_offset_t buf_idx = 0;
+ qpdf_offset_t buf_start = 0;
};
+inline void
+InputSource::loadBuffer()
+{
+ this->buf_idx = 0;
+ this->buf_len = qpdf_offset_t(read(this->buffer, this->buf_size));
+ // NB read sets last_offset
+ this->buf_start = this->last_offset;
+}
+
+inline qpdf_offset_t
+InputSource::fastTell()
+{
+ if (this->buf_len == 0) {
+ loadBuffer();
+ } else {
+ auto curr = tell();
+ if (curr < this->buf_start ||
+ curr >= (this->buf_start + this->buf_len)) {
+ loadBuffer();
+ } else {
+ this->last_offset = curr;
+ this->buf_idx = curr - this->buf_start;
+ }
+ }
+ return this->last_offset;
+}
+
+inline bool
+InputSource::fastRead(char& ch)
+{
+ // Before calling fastRead, fastTell must be called to prepare the buffer.
+ // Once reading is complete, fastUnread must be called to set the correct
+ // file position.
+ if (this->buf_idx < this->buf_len) {
+ ch = this->buffer[this->buf_idx];
+ ++(this->buf_idx);
+ ++(this->last_offset);
+ return true;
+
+ } else if (this->buf_len == 0) {
+ return false;
+ } else {
+ seek(this->buf_start + this->buf_len, SEEK_SET);
+ fastTell();
+ return fastRead(ch);
+ }
+}
+
+inline void
+InputSource::fastUnread(bool back)
+{
+ this->last_offset -= back ? 1 : 0;
+ seek(this->last_offset, SEEK_SET);
+}
+
#endif // QPDF_INPUTSOURCE_HH
diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh
index 64f31edd..81169fbd 100644
--- a/include/qpdf/QPDF.hh
+++ b/include/qpdf/QPDF.hh
@@ -49,6 +49,7 @@ class QPDF_Stream;
class BitStream;
class BitWriter;
class QPDFLogger;
+class QPDFParser;
class QPDF
{
@@ -382,8 +383,15 @@ class QPDF
QPDF_DLL
QPDFObjectHandle makeIndirectObject(QPDFObjectHandle);
- // Retrieve an object by object ID and generation. Returns an
- // indirect reference to it.
+ // Retrieve an object by object ID and generation. Returns an
+ // indirect reference to it. The getObject() methods were added
+ // for qpdf 11.
+ QPDF_DLL
+ QPDFObjectHandle getObject(QPDFObjGen const&);
+ QPDF_DLL
+ QPDFObjectHandle getObject(int objid, int generation);
+ // These are older methods, but there is no intention to deprecate
+ // them.
QPDF_DLL
QPDFObjectHandle getObjectByObjGen(QPDFObjGen const&);
QPDF_DLL
@@ -835,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;
@@ -874,7 +876,7 @@ class QPDF
// resolution
class ParseGuard
{
- friend class QPDFObjectHandle;
+ friend class QPDFParser;
private:
ParseGuard(QPDF* qpdf) :
@@ -1166,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(
@@ -1716,7 +1726,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/QPDFJob.hh b/include/qpdf/QPDFJob.hh
index 0e4d8a2e..2d4ab0d2 100644
--- a/include/qpdf/QPDFJob.hh
+++ b/include/qpdf/QPDFJob.hh
@@ -711,6 +711,7 @@ class QPDFJob
bool json_input;
bool json_output;
std::string update_from_json;
+ bool report_mem_usage;
};
std::shared_ptr<Members> m;
};
diff --git a/include/qpdf/QPDFNameTreeObjectHelper.hh b/include/qpdf/QPDFNameTreeObjectHelper.hh
index 7093ca2e..006ab158 100644
--- a/include/qpdf/QPDFNameTreeObjectHelper.hh
+++ b/include/qpdf/QPDFNameTreeObjectHelper.hh
@@ -42,7 +42,7 @@ class NNTreeImpl;
class NNTreeIterator;
class NNTreeDetails;
-class QPDFNameTreeObjectHelper: public QPDFObjectHelper
+class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper
{
public:
// The qpdf object is required so that this class can issue
@@ -55,7 +55,7 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
QPDF_DLL
- virtual ~QPDFNameTreeObjectHelper() = default;
+ virtual ~QPDFNameTreeObjectHelper();
// Return whether the number tree has an explicit entry for this
// number.
@@ -67,7 +67,7 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
QPDF_DLL
bool findObject(std::string const& utf8, QPDFObjectHandle& oh);
- class iterator
+ class QPDF_DLL_PRIVATE iterator
{
friend class QPDFNameTreeObjectHelper;
@@ -181,7 +181,7 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
void setSplitThreshold(int);
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class QPDFNameTreeObjectHelper;
diff --git a/include/qpdf/QPDFNumberTreeObjectHelper.hh b/include/qpdf/QPDFNumberTreeObjectHelper.hh
index b053b5f4..c1ffc251 100644
--- a/include/qpdf/QPDFNumberTreeObjectHelper.hh
+++ b/include/qpdf/QPDFNumberTreeObjectHelper.hh
@@ -39,7 +39,7 @@ class NNTreeImpl;
class NNTreeIterator;
class NNTreeDetails;
-class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
+class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper
{
public:
// The qpdf object is required so that this class can issue
@@ -49,7 +49,7 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
QPDFObjectHandle, QPDF&, bool auto_repair = true);
QPDF_DLL
- virtual ~QPDFNumberTreeObjectHelper() = default;
+ virtual ~QPDFNumberTreeObjectHelper();
// Create an empty number tree
QPDF_DLL
@@ -85,7 +85,7 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
bool findObjectAtOrBelow(
numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset);
- class iterator
+ class QPDF_DLL_PRIVATE iterator
{
friend class QPDFNumberTreeObjectHelper;
@@ -200,7 +200,7 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
void setSplitThreshold(int);
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class QPDFNumberTreeObjectHelper;
typedef QPDFNumberTreeObjectHelper::numtree_number numtree_number;
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 7ea6b062..16e8dc8b 100644
--- a/include/qpdf/QPDFObjectHandle.hh
+++ b/include/qpdf/QPDFObjectHandle.hh
@@ -43,15 +43,28 @@
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;
class QPDFMatrix;
+class QPDFParser;
class QPDFObjectHandle
{
+ friend class QPDFParser;
+
public:
// This class is used by replaceStreamData. It provides an
// alternative way of associating stream data with a stream. See
@@ -313,13 +326,13 @@ class QPDFObjectHandle
};
QPDF_DLL
- QPDFObjectHandle();
+ QPDFObjectHandle() = default;
QPDF_DLL
QPDFObjectHandle(QPDFObjectHandle const&) = default;
QPDF_DLL
QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
QPDF_DLL
- bool isInitialized() const;
+ inline bool isInitialized() const;
// Return type code and type name of underlying object. These are
// useful for doing rapid type tests (like switch statements) or
@@ -367,7 +380,7 @@ class QPDFObjectHandle
// This returns true in addition to the query for the specific
// type for indirect objects.
QPDF_DLL
- bool isIndirect();
+ inline bool isIndirect() const;
// True for everything except array, dictionary, stream, word, and
// inline image.
@@ -957,9 +970,11 @@ class QPDFObjectHandle
std::set<std::string>* resource_names = nullptr);
// Return the QPDF object that owns an indirect object. Returns
- // null for a direct object.
+ // null for a direct object if allow_nullptr is set to true or
+ // throws a runtime error otherwise.
QPDF_DLL
- QPDF* getOwningQPDF();
+ 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,
@@ -1300,11 +1315,11 @@ class QPDFObjectHandle
// QPDFObjGen instead.
QPDF_DLL
- QPDFObjGen getObjGen() const;
+ inline QPDFObjGen getObjGen() const;
QPDF_DLL
- int getObjectID() const;
+ inline int getObjectID() const;
QPDF_DLL
- int getGeneration() const;
+ inline int getGeneration() const;
QPDF_DLL
std::string unparse();
@@ -1438,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(
@@ -1453,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;
@@ -1478,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;
@@ -1558,27 +1577,32 @@ class QPDFObjectHandle
bool isImage(bool exclude_imagemask = true);
private:
- QPDFObjectHandle(QPDF*, QPDFObjGen const& og);
- QPDFObjectHandle(std::shared_ptr<QPDFObject> const&);
-
- enum parser_state_e {
- st_top,
- st_start,
- st_stop,
- st_eof,
- st_dictionary,
- st_array
- };
+ 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);
@@ -1591,21 +1615,8 @@ class QPDFObjectHandle
bool stop_at_streams);
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
void releaseResolved();
- static void setObjectDescriptionFromInput(
- QPDFObjectHandle,
- QPDF*,
- std::string const&,
- std::shared_ptr<InputSource>,
- qpdf_offset_t);
- static QPDFObjectHandle parseInternal(
- std::shared_ptr<InputSource> input,
- std::string const& object_description,
- QPDFTokenizer& tokenizer,
- bool& empty,
- StringDecrypter* decrypter,
- QPDF* context,
- bool content_stream);
- void setParsedOffset(qpdf_offset_t offset);
+
+ inline void setParsedOffset(qpdf_offset_t offset);
void parseContentStream_internal(
std::string const& description, ParserCallbacks* callbacks);
static void parseContentStream_data(
@@ -1618,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
@@ -1846,4 +1852,58 @@ class QPDFObjectHandle::QPDFArrayItems
QPDFObjectHandle oh;
};
+inline QPDFObjGen
+QPDFObjectHandle::getObjGen() const
+{
+ return isInitialized() ? obj->getObjGen() : QPDFObjGen();
+}
+
+inline int
+QPDFObjectHandle::getObjectID() const
+{
+ return getObjGen().getObj();
+}
+
+inline int
+QPDFObjectHandle::getGeneration() const
+{
+ return getObjGen().getGen();
+}
+
+inline bool
+QPDFObjectHandle::isIndirect() const
+{
+ return (obj != nullptr) && (getObjectID() != 0);
+}
+
+inline bool
+QPDFObjectHandle::isInitialized() const
+{
+ return obj != nullptr;
+}
+
+// Indirect object accessors
+inline QPDF*
+QPDFObjectHandle::getOwningQPDF(
+ bool allow_nullptr, std::string const& error_msg) const
+{
+ // Will be null for direct objects
+ 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 result;
+}
+
+inline void
+QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset)
+{
+ // This is called during parsing on newly created direct objects,
+ // so we can't call dereference() here.
+ if (isInitialized()) {
+ this->obj->setParsedOffset(offset);
+ }
+}
+
#endif // QPDFOBJECTHANDLE_HH
diff --git a/include/qpdf/QPDFTokenizer.hh b/include/qpdf/QPDFTokenizer.hh
index 2187f21e..33b2e710 100644
--- a/include/qpdf/QPDFTokenizer.hh
+++ b/include/qpdf/QPDFTokenizer.hh
@@ -193,60 +193,82 @@ class QPDFTokenizer
QPDFTokenizer(QPDFTokenizer const&) = delete;
QPDFTokenizer& operator=(QPDFTokenizer const&) = delete;
- void resolveLiteral();
bool isSpace(char);
bool isDelimiter(char);
void findEI(std::shared_ptr<InputSource> input);
enum state_e {
st_top,
+ st_in_hexstring,
+ st_in_string,
+ st_in_hexstring_2nd,
+ st_name,
+ st_literal,
st_in_space,
st_in_comment,
- st_in_string,
+ st_string_escape,
+ st_char_code,
+ st_string_after_cr,
st_lt,
st_gt,
- st_literal,
- st_in_hexstring,
st_inline_image,
+ st_sign,
+ st_number,
+ st_real,
+ st_decimal,
+ st_name_hex1,
+ st_name_hex2,
+ st_before_token,
st_token_ready
};
- class Members
- {
- friend class QPDFTokenizer;
-
- public:
- QPDF_DLL
- ~Members() = default;
+ void handleCharacter(char);
+ void inBeforeToken(char);
+ void inTop(char);
+ void inSpace(char);
+ void inComment(char);
+ void inString(char);
+ void inName(char);
+ void inLt(char);
+ void inGt(char);
+ void inStringAfterCR(char);
+ void inStringEscape(char);
+ void inLiteral(char);
+ void inCharCode(char);
+ void inHexstring(char);
+ void inHexstring2nd(char);
+ void inInlineImage(char);
+ void inTokenReady(char);
+ void inNameHex1(char);
+ void inNameHex2(char);
+ void inSign(char);
+ void inDecimal(char);
+ void inNumber(char);
+ void inReal(char);
+ void reset();
- private:
- Members();
- Members(Members const&) = delete;
- void reset();
+ // Lexer state
+ state_e state;
- // Lexer state
- state_e state;
+ bool allow_eof;
+ bool include_ignorable;
- bool allow_eof;
- bool include_ignorable;
+ // Current token accumulation
+ token_type_e type;
+ std::string val;
+ std::string raw_val;
+ std::string error_message;
+ bool before_token;
+ bool in_token;
+ char char_to_unread;
+ size_t inline_image_bytes;
+ bool bad;
- // Current token accumulation
- token_type_e type;
- std::string val;
- std::string raw_val;
- std::string error_message;
- bool unread_char;
- char char_to_unread;
- size_t inline_image_bytes;
-
- // State for strings
- int string_depth;
- bool string_ignoring_newline;
- char bs_num_register[4];
- bool last_char_was_bs;
- bool last_char_was_cr;
- };
- std::shared_ptr<Members> m;
+ // State for strings
+ int string_depth;
+ int char_code;
+ char hex_char;
+ int digit_count;
};
#endif // QPDFTOKENIZER_HH
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
diff --git a/include/qpdf/QTC.hh b/include/qpdf/QTC.hh
index 1fa55901..70115981 100644
--- a/include/qpdf/QTC.hh
+++ b/include/qpdf/QTC.hh
@@ -24,10 +24,24 @@
#include <qpdf/DLL.h>
+// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC
+// calls in any code that includes this file, but QTC will still be
+// built into the library. That way, it is possible to build and
+// package qpdf with QPDF_DISABLE_QTC while still making QTC::TC
+// available to end users.
+
namespace QTC
{
QPDF_DLL
- void TC(char const* const scope, char const* const ccase, int n = 0);
+ void TC_real(char const* const scope, char const* const ccase, int n = 0);
+
+ inline void
+ TC(char const* const scope, char const* const ccase, int n = 0)
+ {
+#ifndef QPDF_DISABLE_QTC
+ TC_real(scope, ccase, n);
+#endif // QPDF_DISABLE_QTC
+ }
}; // namespace QTC
#endif // QTC_HH
diff --git a/include/qpdf/QUtil.hh b/include/qpdf/QUtil.hh
index 32aeae1f..96f4f7ed 100644
--- a/include/qpdf/QUtil.hh
+++ b/include/qpdf/QUtil.hh
@@ -25,6 +25,7 @@
#include <qpdf/DLL.h>
#include <qpdf/PointerHolder.hh>
#include <qpdf/Types.h>
+#include <cstring>
#include <functional>
#include <list>
#include <memory>
@@ -489,16 +490,16 @@ namespace QUtil
// classes without using ctype, which we avoid because of locale
// considerations.
QPDF_DLL
- bool is_hex_digit(char);
+ inline bool is_hex_digit(char);
QPDF_DLL
- bool is_space(char);
+ inline bool is_space(char);
QPDF_DLL
- bool is_digit(char);
+ inline bool is_digit(char);
QPDF_DLL
- bool is_number(char const*);
+ inline bool is_number(char const*);
// This method parses the numeric range syntax used by the qpdf
// command-line tool. May throw std::runtime_error.
@@ -524,6 +525,62 @@ namespace QUtil
wchar_t const* const argv[],
std::function<int(int, char const* const[])> realmain);
#endif // QPDF_NO_WCHAR_T
-}; // namespace QUtil
+
+ // Try to return the maximum amount of memory allocated by the
+ // current process and its threads. Return 0 if unable to
+ // determine. This is Linux-specific and not implemented to be
+ // completely reliable. It is used during development for
+ // performance testing to detect changes that may significantly
+ // change memory usage. It is not recommended for use for other
+ // purposes.
+ QPDF_DLL
+ size_t get_max_memory_usage();
+}; // namespace QUtil
+
+inline bool
+QUtil::is_hex_digit(char ch)
+{
+ return (ch && (strchr("0123456789abcdefABCDEF", ch) != nullptr));
+}
+
+inline bool
+QUtil::is_space(char ch)
+{
+ return (ch && (strchr(" \f\n\r\t\v", ch) != nullptr));
+}
+
+inline bool
+QUtil::is_digit(char ch)
+{
+ return ((ch >= '0') && (ch <= '9'));
+}
+
+inline bool
+QUtil::is_number(char const* p)
+{
+ // ^[\+\-]?(\.\d*|\d+(\.\d*)?)$
+ if (!*p) {
+ return false;
+ }
+ if ((*p == '-') || (*p == '+')) {
+ ++p;
+ }
+ bool found_dot = false;
+ bool found_digit = false;
+ for (; *p; ++p) {
+ if (*p == '.') {
+ if (found_dot) {
+ // only one dot
+ return false;
+ }
+ found_dot = true;
+ } else if (QUtil::is_digit(*p)) {
+ found_digit = true;
+ } else {
+ return false;
+ }
+ }
+ return found_digit;
+}
#endif // QUTIL_HH
diff --git a/include/qpdf/auto_job_c_main.hh b/include/qpdf/auto_job_c_main.hh
index 90927ded..cc655c23 100644
--- a/include/qpdf/auto_job_c_main.hh
+++ b/include/qpdf/auto_job_c_main.hh
@@ -33,6 +33,7 @@ QPDF_DLL Config* qdf();
QPDF_DLL Config* rawStreamData();
QPDF_DLL Config* recompressFlate();
QPDF_DLL Config* removePageLabels();
+QPDF_DLL Config* reportMemUsage();
QPDF_DLL Config* requiresPassword();
QPDF_DLL Config* showEncryption();
QPDF_DLL Config* showEncryptionKey();