Add getTypeCode() and getTypeName()

Add virtual methods to QPDFObject, wrappers to QPDFObjectHandle, and
implementations to all the QPDF_Object types.
This commit is contained in:
Jay Berkenbilt 2013-01-22 09:57:07 -05:00
parent f81152311e
commit 913eb5ac35
33 changed files with 383 additions and 130 deletions

View File

@ -1,10 +1,23 @@
2013-01-22 Jay Berkenbilt <ejb@ql.org>
* Add QPDFObjectHandle::getTypeCode(). This method returns a
unique integer (enumerated type) value corresponding to the object
type of the QPDFObjectHandle. It can be used as an alternative to
the QPDFObjectHandle::is* methods for type testing, particularly
where there is a desire to use a switch statement or optimize for
performance when testing object types.
* Add QPDFObjectHandle::getTypeName(). This method returns a
string literal describing the object type. It is useful for
testing and debugging.
2013-01-20 Jay Berkenbilt <ejb@ql.org>
* Added QPDFObjectHandle::parseContentStream, which parses the
* Add QPDFObjectHandle::parseContentStream, which parses the
objects in a content stream and calls handlers in a callback
class. The example pdf-parse-content illustrates it use.
* Added QPDF_Keyword and QPDF_InlineImage types along with
* Add QPDF_Keyword and QPDF_InlineImage types along with
appropriate wrapper methods in QPDFObjectHandle. These new object
types are to facilitate content stream parsing.

View File

@ -30,10 +30,10 @@ class ParserCallbacks: public QPDFObjectHandle::ParserCallbacks
void
ParserCallbacks::handleObject(QPDFObjectHandle obj)
{
std::cout << obj.getTypeName() << ": ";
if (obj.isInlineImage())
{
std::string val = obj.getInlineImageValue();
std::cout << "inline image: ";
char buf[3];
buf[2] = '\0';
for (size_t i = 0; i < val.length(); ++i)

View File

@ -1,11 +1,11 @@
BT
/F1
24
Tf
72
720
Td
(Potato)
Tj
ET
keyword: BT
name: /F1
integer: 24
keyword: Tf
integer: 72
integer: 720
keyword: Td
string: (Potato)
keyword: Tj
keyword: ET
-EOF-

View File

@ -18,9 +18,42 @@ class QPDFObjectHandle;
class QPDFObject
{
public:
// Objects derived from QPDFObject are accessible through
// QPDFObjectHandle. Each object returns a unique type code that
// has one of the values in the list below. As new object types
// are added to qpdf, additional items may be added to the list,
// so code that switches on these values should take that into
// consideration.
enum object_type_e {
// Object types internal to qpdf
ot_uninitialized,
ot_reserved,
// Object types that can occur in the main document
ot_boolean,
ot_null,
ot_integer,
ot_real,
ot_name,
ot_string,
ot_array,
ot_dictionary,
ot_stream,
// Additional object types that can occur in content streams
ot_keyword,
ot_inlineimage,
};
virtual ~QPDFObject() {}
virtual std::string unparse() = 0;
// Return a unique type code for the object
virtual object_type_e getTypeCode() const = 0;
// Return a string literal that describes the type, useful for
// debugging and testing
virtual char const* getTypeName() const = 0;
// Accessor to give specific access to non-public methods
class ObjAccessor
{

View File

@ -91,6 +91,14 @@ class QPDFObjectHandle
QPDF_DLL
bool isInitialized() const;
// 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
QPDFObject::object_type_e getTypeCode() const;
QPDF_DLL
char const* getTypeName() const;
// Exactly one of these will return true for any object. Keyword
// and InlineImage are only allowed in content streams.
QPDF_DLL

View File

@ -76,6 +76,32 @@ QPDFObjectHandle::isInitialized() const
return this->initialized;
}
QPDFObject::object_type_e
QPDFObjectHandle::getTypeCode() const
{
if (obj.getPointer())
{
return obj->getTypeCode();
}
else
{
return QPDFObject::ot_uninitialized;
}
}
char const*
QPDFObjectHandle::getTypeName() const
{
if (obj.getPointer())
{
return obj->getTypeName();
}
else
{
return "uninitialized";
}
}
template <class T>
class QPDFObjectTypeAccessor
{

View File

@ -34,6 +34,18 @@ QPDF_Array::unparse()
return result;
}
QPDFObject::object_type_e
QPDF_Array::getTypeCode() const
{
return QPDFObject::ot_array;
}
char const*
QPDF_Array::getTypeName() const
{
return "array";
}
int
QPDF_Array::getNItems() const
{

View File

@ -15,6 +15,18 @@ QPDF_Bool::unparse()
return (val ? "true" : "false");
}
QPDFObject::object_type_e
QPDF_Bool::getTypeCode() const
{
return QPDFObject::ot_boolean;
}
char const*
QPDF_Bool::getTypeName() const
{
return "boolean";
}
bool
QPDF_Bool::getVal() const
{

View File

@ -39,6 +39,18 @@ QPDF_Dictionary::unparse()
return result;
}
QPDFObject::object_type_e
QPDF_Dictionary::getTypeCode() const
{
return QPDFObject::ot_dictionary;
}
char const*
QPDF_Dictionary::getTypeName() const
{
return "dictionary";
}
bool
QPDF_Dictionary::hasKey(std::string const& key)
{

View File

@ -17,6 +17,18 @@ QPDF_InlineImage::unparse()
return this->val;
}
QPDFObject::object_type_e
QPDF_InlineImage::getTypeCode() const
{
return QPDFObject::ot_inlineimage;
}
char const*
QPDF_InlineImage::getTypeName() const
{
return "inline-image";
}
std::string
QPDF_InlineImage::getVal() const
{

View File

@ -17,6 +17,18 @@ QPDF_Integer::unparse()
return QUtil::int_to_string(this->val);
}
QPDFObject::object_type_e
QPDF_Integer::getTypeCode() const
{
return QPDFObject::ot_integer;
}
char const*
QPDF_Integer::getTypeName() const
{
return "integer";
}
long long
QPDF_Integer::getVal() const
{

View File

@ -17,6 +17,18 @@ QPDF_Keyword::unparse()
return this->val;
}
QPDFObject::object_type_e
QPDF_Keyword::getTypeCode() const
{
return QPDFObject::ot_keyword;
}
char const*
QPDF_Keyword::getTypeName() const
{
return "keyword";
}
std::string
QPDF_Keyword::getVal() const
{

View File

@ -41,6 +41,18 @@ QPDF_Name::unparse()
return normalizeName(this->name);
}
QPDFObject::object_type_e
QPDF_Name::getTypeCode() const
{
return QPDFObject::ot_name;
}
char const*
QPDF_Name::getTypeName() const
{
return "name";
}
std::string
QPDF_Name::getName() const
{

View File

@ -9,3 +9,15 @@ QPDF_Null::unparse()
{
return "null";
}
QPDFObject::object_type_e
QPDF_Null::getTypeCode() const
{
return QPDFObject::ot_null;
}
char const*
QPDF_Null::getTypeName() const
{
return "null";
}

View File

@ -22,6 +22,18 @@ QPDF_Real::unparse()
return this->val;
}
QPDFObject::object_type_e
QPDF_Real::getTypeCode() const
{
return QPDFObject::ot_real;
}
char const*
QPDF_Real::getTypeName() const
{
return "real";
}
std::string
QPDF_Real::getVal()
{

View File

@ -11,3 +11,15 @@ QPDF_Reserved::unparse()
throw std::logic_error("attempt to unparse QPDF_Reserved");
return "";
}
QPDFObject::object_type_e
QPDF_Reserved::getTypeCode() const
{
return QPDFObject::ot_reserved;
}
char const*
QPDF_Reserved::getTypeName() const
{
return "reserved";
}

View File

@ -63,6 +63,18 @@ QPDF_Stream::unparse()
QUtil::int_to_string(this->generation) + " R";
}
QPDFObject::object_type_e
QPDF_Stream::getTypeCode() const
{
return QPDFObject::ot_stream;
}
char const*
QPDF_Stream::getTypeName() const
{
return "stream";
}
QPDFObjectHandle
QPDF_Stream::getDict() const
{

View File

@ -33,6 +33,18 @@ QPDF_String::unparse()
return unparse(false);
}
QPDFObject::object_type_e
QPDF_String::getTypeCode() const
{
return QPDFObject::ot_string;
}
char const*
QPDF_String::getTypeName() const
{
return "string";
}
std::string
QPDF_String::unparse(bool force_binary)
{

View File

@ -12,6 +12,8 @@ class QPDF_Array: public QPDFObject
QPDF_Array(std::vector<QPDFObjectHandle> const& items);
virtual ~QPDF_Array();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
int getNItems() const;
QPDFObjectHandle getItem(int n) const;

View File

@ -9,6 +9,8 @@ class QPDF_Bool: public QPDFObject
QPDF_Bool(bool val);
virtual ~QPDF_Bool();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
bool getVal() const;
private:

View File

@ -14,6 +14,8 @@ class QPDF_Dictionary: public QPDFObject
QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items);
virtual ~QPDF_Dictionary();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
// hasKey() and getKeys() treat keys with null values as if they
// aren't there. getKey() returns null for the value of a

View File

@ -9,6 +9,8 @@ class QPDF_InlineImage: public QPDFObject
QPDF_InlineImage(std::string const& val);
virtual ~QPDF_InlineImage();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
std::string getVal() const;
private:

View File

@ -9,6 +9,8 @@ class QPDF_Integer: public QPDFObject
QPDF_Integer(long long val);
virtual ~QPDF_Integer();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
long long getVal() const;
private:

View File

@ -9,6 +9,8 @@ class QPDF_Keyword: public QPDFObject
QPDF_Keyword(std::string const& val);
virtual ~QPDF_Keyword();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
std::string getVal() const;
private:

View File

@ -9,6 +9,8 @@ class QPDF_Name: public QPDFObject
QPDF_Name(std::string const& name);
virtual ~QPDF_Name();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
std::string getName() const;
// Put # into strings with characters unsuitable for name token

View File

@ -8,6 +8,8 @@ class QPDF_Null: public QPDFObject
public:
virtual ~QPDF_Null();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
};
#endif // __QPDF_NULL_HH__

View File

@ -10,6 +10,8 @@ class QPDF_Real: public QPDFObject
QPDF_Real(double value, int decimal_places = 0);
virtual ~QPDF_Real();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
std::string getVal();
private:

View File

@ -8,6 +8,8 @@ class QPDF_Reserved: public QPDFObject
public:
virtual ~QPDF_Reserved();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
};
#endif // __QPDF_RESERVED_HH__

View File

@ -17,6 +17,8 @@ class QPDF_Stream: public QPDFObject
qpdf_offset_t offset, size_t length);
virtual ~QPDF_Stream();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
QPDFObjectHandle getDict() const;
// See comments in QPDFObjectHandle.hh for these methods.

View File

@ -11,6 +11,8 @@ class QPDF_String: public QPDFObject
QPDF_String(std::string const& val);
virtual ~QPDF_String();
virtual std::string unparse();
virtual QPDFObject::object_type_e getTypeCode() const;
virtual char const* getTypeName() const;
std::string unparse(bool force_binary);
std::string getVal() const;
std::string getUTF8Val() const;

View File

@ -1,25 +1,25 @@
BT
/F1
24
Tf
72
720
Td
(Potato)
Tj
ET
BI
/CS
/G
/W
1
/H
1
/BPC
8
/F
/Fl
/DP
<< /Columns 1 /Predictor 15 >>
ID
keyword: BT
name: /F1
integer: 24
keyword: Tf
integer: 72
integer: 720
keyword: Td
string: (Potato)
keyword: Tj
keyword: ET
keyword: BI
name: /CS
name: /G
name: /W
integer: 1
name: /H
integer: 1
name: /BPC
integer: 8
name: /F
name: /Fl
name: /DP
dictionary: << /Columns 1 /Predictor 15 >>
keyword: ID
content stream object 4 0 (stream data, file position 139): EOF found while reading inline image

View File

@ -1,95 +1,95 @@
BT
/F1
24
Tf
72
720
Td
(Potato)
Tj
ET
keyword: BT
name: /F1
integer: 24
keyword: Tf
integer: 72
integer: 720
keyword: Td
string: (Potato)
keyword: Tj
keyword: ET
-EOF-
0.1
0
0
0.1
0
0
cm
q
0
1.1999
-1.1999
0
121.19
150.009
cm
BI
/CS
/G
/W
1
/H
1
/BPC
8
/F
/Fl
/DP
<< /Columns 1 /Predictor 15 >>
ID
inline image: 789c63fc0f0001030101
EI
Q
q
0
35.997
-128.389
0
431.964
7269.02
cm
BI
/CS
/G
/W
30
/H
107
/BPC
8
/F
/Fl
/DP
<< /Columns 30 /Predictor 15 >>
ID
inline image: 789cedd1a11100300800b1b2ffd06503148283bc8dfcf8af2a306ee352eff2e06318638c31c63b3801627b620a
EI
Q
q
0
38.3968
-93.5922
0
431.964
7567.79
cm
BI
/CS
/G
/W
32
/H
78
/BPC
8
/F
/Fl
/DP
<< /Columns 32 /Predictor 15 >>
ID
inline image: 789c63fccf801f308e2a185530aa60882a20203faa605401890a0643aa1e5530aa6054010d140000bdd03c13
EI
Q
real: 0.1
integer: 0
integer: 0
real: 0.1
integer: 0
integer: 0
keyword: cm
keyword: q
integer: 0
real: 1.1999
real: -1.1999
integer: 0
real: 121.19
real: 150.009
keyword: cm
keyword: BI
name: /CS
name: /G
name: /W
integer: 1
name: /H
integer: 1
name: /BPC
integer: 8
name: /F
name: /Fl
name: /DP
dictionary: << /Columns 1 /Predictor 15 >>
keyword: ID
inline-image: 789c63fc0f0001030101
keyword: EI
keyword: Q
keyword: q
integer: 0
real: 35.997
real: -128.389
integer: 0
real: 431.964
real: 7269.02
keyword: cm
keyword: BI
name: /CS
name: /G
name: /W
integer: 30
name: /H
integer: 107
name: /BPC
integer: 8
name: /F
name: /Fl
name: /DP
dictionary: << /Columns 30 /Predictor 15 >>
keyword: ID
inline-image: 789cedd1a11100300800b1b2ffd06503148283bc8dfcf8af2a306ee352eff2e06318638c31c63b3801627b620a
keyword: EI
keyword: Q
keyword: q
integer: 0
real: 38.3968
real: -93.5922
integer: 0
real: 431.964
real: 7567.79
keyword: cm
keyword: BI
name: /CS
name: /G
name: /W
integer: 32
name: /H
integer: 78
name: /BPC
integer: 8
name: /F
name: /Fl
name: /DP
dictionary: << /Columns 32 /Predictor 15 >>
keyword: ID
inline-image: 789c63fccf801f308e2a185530aa60882a20203faa605401890a0643aa1e5530aa6054010d140000bdd03c13
keyword: EI
keyword: Q
-EOF-
test 37 done

View File

@ -72,10 +72,11 @@ class ParserCallbacks: public QPDFObjectHandle::ParserCallbacks
void
ParserCallbacks::handleObject(QPDFObjectHandle obj)
{
std::cout << obj.getTypeName() << ": ";
if (obj.isInlineImage())
{
assert(obj.getTypeCode() == QPDFObject::ot_inlineimage);
std::string val = obj.getInlineImageValue();
std::cout << "inline image: ";
char buf[3];
buf[2] = '\0';
for (size_t i = 0; i < val.length(); ++i)
@ -142,6 +143,10 @@ void runtest(int n, char const* filename1, char const* arg2)
assert(password.length() == 32);
QPDF::trim_user_password(password);
assert(password == "1234567890123456789012(45678");
QPDFObjectHandle uninitialized;
assert(uninitialized.getTypeCode() == QPDFObject::ot_uninitialized);
assert(strcmp(uninitialized.getTypeName(), "uninitialized") == 0);
}
QPDF pdf;