diff --git a/ChangeLog b/ChangeLog index c1024773..dbd589fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2018-12-18 Jay Berkenbilt + * New method QPDFObjectHandle::getJSON() returns a JSON object + with a partial representation of the object. See + QPDFObjectHandle.hh for a detailed description. + * Add a simple JSON serializer. This is not a complete or general-purpose JSON library. It allows assembly and serialization of JSON structures with some restrictions, which are described in diff --git a/include/qpdf/QPDFObject.hh b/include/qpdf/QPDFObject.hh index 0bc4a03c..37dfeecf 100644 --- a/include/qpdf/QPDFObject.hh +++ b/include/qpdf/QPDFObject.hh @@ -24,6 +24,7 @@ #include #include +#include #include @@ -62,6 +63,7 @@ class QPDFObject virtual ~QPDFObject() {} virtual std::string unparse() = 0; + virtual JSON getJSON() = 0; // Return a unique type code for the object virtual object_type_e getTypeCode() const = 0; diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 88f071d2..9cc67686 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -733,6 +733,25 @@ class QPDFObjectHandle QPDF_DLL std::string unparseBinary(); + // Return encoded as JSON. For most object types, there is an + // obvious mapping. The JSON is generated as follows: + // * Names are encoded as strings representing the normalized value of + // getName() + // * Indirect references are encoded as strings containing "obj gen R" + // * Strings are encoded as UTF-8 strings with unrepresentable binary + // characters encoded as \uHHHH + // * Encoding streams just encodes the stream's dictionary; the stream + // data is not represented + // * Object types that are only valid in content streams (inline + // image, operator) as well as "reserved" objects are not + // representable and will be serialized as "null". + // If dereference_indirect is true and this is an indirect object, + // show the actual contents of the object. The effect of + // dereference_indirect applies only to this object. It is not + // recursive. + QPDF_DLL + JSON getJSON(bool dereference_indirect = false); + // Legacy helper methods for commonly performed operations on // pages. Newer code should use QPDFPageObjectHelper instead. The // specification and behavior of these methods are the same as the diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index f26ee931..d0373d63 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -1235,6 +1235,25 @@ QPDFObjectHandle::unparseBinary() } } +JSON +QPDFObjectHandle::getJSON(bool dereference_indirect) +{ + if ((! dereference_indirect) && this->isIndirect()) + { + return JSON::makeString(unparse()); + } + else + { + if (this->m->reserved) + { + throw std::logic_error( + "QPDFObjectHandle: attempting to unparse a reserved object"); + } + dereference(); + return this->m->obj->getJSON(); + } +} + QPDFObjectHandle QPDFObjectHandle::wrapInArray() { diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 1a4ba61d..15c2e93e 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -35,6 +35,18 @@ QPDF_Array::unparse() return result; } +JSON +QPDF_Array::getJSON() +{ + JSON j = JSON::makeArray(); + for (std::vector::iterator iter = this->items.begin(); + iter != this->items.end(); ++iter) + { + j.addArrayElement((*iter).getJSON()); + } + return j; +} + QPDFObject::object_type_e QPDF_Array::getTypeCode() const { diff --git a/libqpdf/QPDF_Bool.cc b/libqpdf/QPDF_Bool.cc index 781a7ad9..63d44adb 100644 --- a/libqpdf/QPDF_Bool.cc +++ b/libqpdf/QPDF_Bool.cc @@ -15,6 +15,12 @@ QPDF_Bool::unparse() return (val ? "true" : "false"); } +JSON +QPDF_Bool::getJSON() +{ + return JSON::makeBool(this->val); +} + QPDFObject::object_type_e QPDF_Bool::getTypeCode() const { diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc index df640354..1301d46f 100644 --- a/libqpdf/QPDF_Dictionary.cc +++ b/libqpdf/QPDF_Dictionary.cc @@ -39,6 +39,20 @@ QPDF_Dictionary::unparse() return result; } +JSON +QPDF_Dictionary::getJSON() +{ + JSON j = JSON::makeDictionary(); + for (std::map::iterator iter = + this->items.begin(); + iter != this->items.end(); ++iter) + { + j.addDictionaryMember(QPDF_Name::normalizeName((*iter).first), + (*iter).second.getJSON()); + } + return j; +} + QPDFObject::object_type_e QPDF_Dictionary::getTypeCode() const { diff --git a/libqpdf/QPDF_InlineImage.cc b/libqpdf/QPDF_InlineImage.cc index 48be6387..9769630c 100644 --- a/libqpdf/QPDF_InlineImage.cc +++ b/libqpdf/QPDF_InlineImage.cc @@ -17,6 +17,12 @@ QPDF_InlineImage::unparse() return this->val; } +JSON +QPDF_InlineImage::getJSON() +{ + return JSON::makeNull(); +} + QPDFObject::object_type_e QPDF_InlineImage::getTypeCode() const { diff --git a/libqpdf/QPDF_Integer.cc b/libqpdf/QPDF_Integer.cc index 572b34e0..d0356dad 100644 --- a/libqpdf/QPDF_Integer.cc +++ b/libqpdf/QPDF_Integer.cc @@ -17,6 +17,12 @@ QPDF_Integer::unparse() return QUtil::int_to_string(this->val); } +JSON +QPDF_Integer::getJSON() +{ + return JSON::makeInt(this->val); +} + QPDFObject::object_type_e QPDF_Integer::getTypeCode() const { diff --git a/libqpdf/QPDF_Name.cc b/libqpdf/QPDF_Name.cc index 0c2082c4..290fb067 100644 --- a/libqpdf/QPDF_Name.cc +++ b/libqpdf/QPDF_Name.cc @@ -44,6 +44,12 @@ QPDF_Name::unparse() return normalizeName(this->name); } +JSON +QPDF_Name::getJSON() +{ + return JSON::makeString(normalizeName(this->name)); +} + QPDFObject::object_type_e QPDF_Name::getTypeCode() const { diff --git a/libqpdf/QPDF_Null.cc b/libqpdf/QPDF_Null.cc index 05c35b09..e4193c6c 100644 --- a/libqpdf/QPDF_Null.cc +++ b/libqpdf/QPDF_Null.cc @@ -10,6 +10,12 @@ QPDF_Null::unparse() return "null"; } +JSON +QPDF_Null::getJSON() +{ + return JSON::makeNull(); +} + QPDFObject::object_type_e QPDF_Null::getTypeCode() const { diff --git a/libqpdf/QPDF_Operator.cc b/libqpdf/QPDF_Operator.cc index c6c68816..b61d47b1 100644 --- a/libqpdf/QPDF_Operator.cc +++ b/libqpdf/QPDF_Operator.cc @@ -17,6 +17,12 @@ QPDF_Operator::unparse() return this->val; } +JSON +QPDF_Operator::getJSON() +{ + return JSON::makeNull(); +} + QPDFObject::object_type_e QPDF_Operator::getTypeCode() const { diff --git a/libqpdf/QPDF_Real.cc b/libqpdf/QPDF_Real.cc index fa0a60cb..b28c2f70 100644 --- a/libqpdf/QPDF_Real.cc +++ b/libqpdf/QPDF_Real.cc @@ -22,6 +22,12 @@ QPDF_Real::unparse() return this->val; } +JSON +QPDF_Real::getJSON() +{ + return JSON::makeNumber(this->val); +} + QPDFObject::object_type_e QPDF_Real::getTypeCode() const { diff --git a/libqpdf/QPDF_Reserved.cc b/libqpdf/QPDF_Reserved.cc index ad8d94a3..6cce2f2a 100644 --- a/libqpdf/QPDF_Reserved.cc +++ b/libqpdf/QPDF_Reserved.cc @@ -12,6 +12,13 @@ QPDF_Reserved::unparse() return ""; } +JSON +QPDF_Reserved::getJSON() +{ + throw std::logic_error("attempt to generate JSON from QPDF_Reserved"); + return JSON::makeNull(); +} + QPDFObject::object_type_e QPDF_Reserved::getTypeCode() const { diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 384652e2..0a5f53b4 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -74,6 +74,12 @@ QPDF_Stream::unparse() QUtil::int_to_string(this->generation) + " R"; } +JSON +QPDF_Stream::getJSON() +{ + return this->stream_dict.getJSON(); +} + QPDFObject::object_type_e QPDF_Stream::getTypeCode() const { diff --git a/libqpdf/QPDF_String.cc b/libqpdf/QPDF_String.cc index eb31a808..809823a6 100644 --- a/libqpdf/QPDF_String.cc +++ b/libqpdf/QPDF_String.cc @@ -122,6 +122,12 @@ QPDF_String::unparse() return unparse(false); } +JSON +QPDF_String::getJSON() +{ + return JSON::makeString(getUTF8Val()); +} + QPDFObject::object_type_e QPDF_String::getTypeCode() const { diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 3681686f..695e6587 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -12,6 +12,7 @@ class QPDF_Array: public QPDFObject QPDF_Array(std::vector const& items); virtual ~QPDF_Array(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; virtual void setDescription(QPDF*, std::string const&); diff --git a/libqpdf/qpdf/QPDF_Bool.hh b/libqpdf/qpdf/QPDF_Bool.hh index 72b4a509..5da6e87c 100644 --- a/libqpdf/qpdf/QPDF_Bool.hh +++ b/libqpdf/qpdf/QPDF_Bool.hh @@ -9,6 +9,7 @@ class QPDF_Bool: public QPDFObject QPDF_Bool(bool val); virtual ~QPDF_Bool(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; bool getVal() const; diff --git a/libqpdf/qpdf/QPDF_Dictionary.hh b/libqpdf/qpdf/QPDF_Dictionary.hh index aa519fa5..4ea3ae7d 100644 --- a/libqpdf/qpdf/QPDF_Dictionary.hh +++ b/libqpdf/qpdf/QPDF_Dictionary.hh @@ -14,6 +14,7 @@ class QPDF_Dictionary: public QPDFObject QPDF_Dictionary(std::map const& items); virtual ~QPDF_Dictionary(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; virtual void setDescription(QPDF*, std::string const&); diff --git a/libqpdf/qpdf/QPDF_InlineImage.hh b/libqpdf/qpdf/QPDF_InlineImage.hh index f3a9269f..bc544c39 100644 --- a/libqpdf/qpdf/QPDF_InlineImage.hh +++ b/libqpdf/qpdf/QPDF_InlineImage.hh @@ -9,6 +9,7 @@ class QPDF_InlineImage: public QPDFObject QPDF_InlineImage(std::string const& val); virtual ~QPDF_InlineImage(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; std::string getVal() const; diff --git a/libqpdf/qpdf/QPDF_Integer.hh b/libqpdf/qpdf/QPDF_Integer.hh index b9459384..35e11a94 100644 --- a/libqpdf/qpdf/QPDF_Integer.hh +++ b/libqpdf/qpdf/QPDF_Integer.hh @@ -9,6 +9,7 @@ class QPDF_Integer: public QPDFObject QPDF_Integer(long long val); virtual ~QPDF_Integer(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; long long getVal() const; diff --git a/libqpdf/qpdf/QPDF_Name.hh b/libqpdf/qpdf/QPDF_Name.hh index 2f240fe5..f87ca460 100644 --- a/libqpdf/qpdf/QPDF_Name.hh +++ b/libqpdf/qpdf/QPDF_Name.hh @@ -9,6 +9,7 @@ class QPDF_Name: public QPDFObject QPDF_Name(std::string const& name); virtual ~QPDF_Name(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; std::string getName() const; diff --git a/libqpdf/qpdf/QPDF_Null.hh b/libqpdf/qpdf/QPDF_Null.hh index e55193c7..667c72f9 100644 --- a/libqpdf/qpdf/QPDF_Null.hh +++ b/libqpdf/qpdf/QPDF_Null.hh @@ -8,6 +8,7 @@ class QPDF_Null: public QPDFObject public: virtual ~QPDF_Null(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; }; diff --git a/libqpdf/qpdf/QPDF_Operator.hh b/libqpdf/qpdf/QPDF_Operator.hh index 4bf40066..4b3787a0 100644 --- a/libqpdf/qpdf/QPDF_Operator.hh +++ b/libqpdf/qpdf/QPDF_Operator.hh @@ -9,6 +9,7 @@ class QPDF_Operator: public QPDFObject QPDF_Operator(std::string const& val); virtual ~QPDF_Operator(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; std::string getVal() const; diff --git a/libqpdf/qpdf/QPDF_Real.hh b/libqpdf/qpdf/QPDF_Real.hh index 1a523dcf..dbc03de6 100644 --- a/libqpdf/qpdf/QPDF_Real.hh +++ b/libqpdf/qpdf/QPDF_Real.hh @@ -10,6 +10,7 @@ class QPDF_Real: public QPDFObject QPDF_Real(double value, int decimal_places = 0); virtual ~QPDF_Real(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; std::string getVal(); diff --git a/libqpdf/qpdf/QPDF_Reserved.hh b/libqpdf/qpdf/QPDF_Reserved.hh index 8062abb1..71adbf3a 100644 --- a/libqpdf/qpdf/QPDF_Reserved.hh +++ b/libqpdf/qpdf/QPDF_Reserved.hh @@ -8,6 +8,7 @@ class QPDF_Reserved: public QPDFObject public: virtual ~QPDF_Reserved(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; }; diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh index 7af2ffc2..b38bed08 100644 --- a/libqpdf/qpdf/QPDF_Stream.hh +++ b/libqpdf/qpdf/QPDF_Stream.hh @@ -17,6 +17,7 @@ class QPDF_Stream: public QPDFObject qpdf_offset_t offset, size_t length); virtual ~QPDF_Stream(); virtual std::string unparse(); + virtual JSON getJSON(); virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; virtual void setDescription(QPDF*, std::string const&); diff --git a/libqpdf/qpdf/QPDF_String.hh b/libqpdf/qpdf/QPDF_String.hh index 377b0900..1c7bb639 100644 --- a/libqpdf/qpdf/QPDF_String.hh +++ b/libqpdf/qpdf/QPDF_String.hh @@ -15,6 +15,7 @@ class QPDF_String: public QPDFObject virtual QPDFObject::object_type_e getTypeCode() const; virtual char const* getTypeName() const; std::string unparse(bool force_binary); + virtual JSON getJSON(); std::string getVal() const; std::string getUTF8Val() const;