// Copyright (c) 2005-2008 Jay Berkenbilt // // This file is part of qpdf. This software may be distributed under // the terms of version 2 of the Artistic License which may be found // in the source distribution. It is provided "as is" without express // or implied warranty. #ifndef __QPDFOBJECTHANDLE_HH__ #define __QPDFOBJECTHANDLE_HH__ #include #include #include #include #include #include #include class Pipeline; class QPDF; class QPDFObjectHandle { public: QPDFObjectHandle(); bool isInitialized() const; // Exactly one of these will return true for any object. bool isBool(); bool isNull(); bool isInteger(); bool isReal(); bool isName(); bool isString(); bool isArray(); bool isDictionary(); bool isStream(); // This returns true in addition to the query for the specific // type for indirect objects. bool isIndirect(); // True for everything except array, dictionary, and stream bool isScalar(); // Public factory methods static QPDFObjectHandle newNull(); static QPDFObjectHandle newBool(bool value); static QPDFObjectHandle newInteger(int value); static QPDFObjectHandle newReal(std::string const& value); static QPDFObjectHandle newName(std::string const& name); static QPDFObjectHandle newString(std::string const& str); static QPDFObjectHandle newArray( std::vector const& items); static QPDFObjectHandle newDictionary( std::map const& items); // Accessor methods. If an accessor method that is valid for only // a particular object type is called on an object of the wrong // type, an exception is thrown. // Methods for bool objects bool getBoolValue(); // Methods for integer objects int getIntValue(); // Methods for real objects std::string getRealValue(); // Methods that work for both integer and real objects bool isNumber(); double getNumericValue(); // Methods for name objects std::string getName(); // Methods for string objects std::string getStringValue(); std::string getUTF8Value(); // Methods for array objects int getArrayNItems(); QPDFObjectHandle getArrayItem(int n); // Methods for dictionary objects bool hasKey(std::string const&); QPDFObjectHandle getKey(std::string const&); std::set getKeys(); // Mutator methods. Use with caution. // Recursively copy this object, making it direct. Throws an // exception if a loop is detected or any sub-object is a stream. void makeDirect(); // Mutator methods for array objects void setArrayItem(int, QPDFObjectHandle const&); // Mutator methods for dictionary objects // Replace value of key, adding it if it does not exist void replaceKey(std::string const& key, QPDFObjectHandle const&); // Remove key, doing nothing if key does not exist void removeKey(std::string const& key); // Methods for stream objects QPDFObjectHandle getDict(); // Returns filtered (uncompressed) stream data. Throws an // exception if the stream is filtered and we can't decode it. PointerHolder getStreamData(); // Write stream data through the given pipeline. A null pipeline // value may be used if all you want to do is determine whether a // stream is filterable. If filter is false, write raw stream // data and return false. If filter is true, then attempt to // apply all the decoding filters to the stream data. If we are // successful, return true. Otherwise, return false and write raw // data. If filtering is requested and successfully performed, // then the normalize and compress flags are used to determine // whether stream data should be normalized and compressed. In // all cases, if this function returns false, raw data has been // written. If it returns true, then any requested filtering has // been performed. Note that if the original stream data has no // filters applied to it, the return value will be equal to the // value of the filter parameter. Callers may use the return // value of this function to determine whether or not the /Filter // and /DecodeParms keys in the stream dictionary should be // replaced if writing a new stream object. bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress); // return 0 for direct objects int getObjectID() const; int getGeneration() const; std::string unparse(); std::string unparseResolved(); // Convenience routines for commonly performed functions // Throws an exception if this is not a Page object. Returns an // empty map if there are no images or no resources. This // function does not presently support inherited resources. See // comment in the source for details. Return value is a map from // XObject name to the image object, which is always a stream. std::map getPageImages(); // Throws an exception if this is not a Page object. Returns a // vector of stream objects representing the content streams for // the given page. This routine allows the caller to not care // whether there are one or more than one content streams for a // page. std::vector getPageContents(); // Initializers for objects. This Factory class gives the QPDF // class specific permission to call factory methods without // making it a friend of the whole QPDFObjectHandle class. class Factory { friend class QPDF; private: static QPDFObjectHandle newIndirect(QPDF* qpdf, int objid, int generation) { return QPDFObjectHandle::newIndirect(qpdf, objid, generation); } // object must be dictionary object static QPDFObjectHandle newStream( QPDF* qpdf, int objid, int generation, QPDFObjectHandle stream_dict, off_t offset, int length) { return QPDFObjectHandle::newStream( qpdf, objid, generation, stream_dict, offset, length); } }; friend class Factory; // Accessor for raw underlying object -- only QPDF is allowed to // call this. class ObjAccessor { friend class QPDF; private: static PointerHolder getObject(QPDFObjectHandle& o) { o.dereference(); return o.obj; } }; friend class ObjAccessor; private: QPDFObjectHandle(QPDF*, int objid, int generation); QPDFObjectHandle(QPDFObject*); // Private object factory methods static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation); static QPDFObjectHandle newStream( QPDF* qpdf, int objid, int generation, QPDFObjectHandle stream_dict, off_t offset, int length); void assertInitialized() const; void assertType(char const* type_name, bool istype); void assertPageObject(); void dereference(); void makeDirectInternal(std::set& visited); bool initialized; QPDF* qpdf; // 0 for direct object int objid; // 0 for direct object int generation; PointerHolder obj; }; #endif // __QPDFOBJECTHANDLE_HH__