ready to implement replacement stream data

git-svn-id: svn+q:///qpdf/trunk@987 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
Jay Berkenbilt 2010-08-02 22:17:01 +00:00
parent ab5a01c64e
commit 9a06fc541c
6 changed files with 132 additions and 4 deletions

View File

@ -152,6 +152,9 @@ class QPDFObjectHandle
// Remove key, doing nothing if key does not exist
QPDF_DLL
void removeKey(std::string const& key);
// If the object is null, remove the key. Otherwise, replace it.
QPDF_DLL
void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle);
// Methods for stream objects
QPDF_DLL
@ -183,6 +186,64 @@ class QPDFObjectHandle
bool pipeStreamData(Pipeline*, bool filter,
bool normalize, bool compress);
// Replace this stream's stream data with the given data buffer,
// and replace the /Filter and /DecodeParms keys in the stream
// dictionary with the given values. (If either value is empty,
// the corresponding key is removed.) The stream's /Length key is
// replaced with the length of the data buffer. The stream is
// interpreted as if the data read from the file, after any
// decryption filters have been applied, is as presented.
QPDF_DLL
void replaceStreamData(PointerHolder<Buffer> data,
QPDFObjectHandle filter,
QPDFObjectHandle decode_parms);
class StreamDataHandler
{
public:
QPDF_DLL
virtual ~StreamDataHandler()
{
}
// See replaceStreamData(StreamDataHandler) below for a
// description of how to override this function.
virtual void
replaceStreamData(Buffer const& in_data,
std::string const& in_filter,
std::string const& in_decode_parms,
bool filtered,
Buffer& out_data,
std::string& out_filter,
std::string& out_decode_parms,
bool& persist) = 0;
};
// Provide a hook for doing dynamic replacement of the stream's
// data. When the stream's data is accessed either with
// pipeStreamData or with getStreamData, if the stream doesn't
// already have replacement data, an attempt is first made to
// filter the stream's original data. If the attempt is
// successful, the stream's filtered original data is passed to
// the handler as in_data, and filtered is true. If the original
// data cannot be processed, then in_data is the original raw data
// (after any decryption filters have been applied) and filtered
// is false. If the original input data has no filters applied,
// the filtered is true. This way, if filtered is true, the
// caller knows that in_data contains the fully filtered data.
// The handler then provides replacement data, /Filter, and
// /DecodeParms (handled is in the simpler form of
// replaceStreamData above). If the persist argument is set to
// true, then the replacement data is stored in the stream object
// where it will be used on subsequent attempts to retrieve the
// data (rather than calling the handler). If persist is set to
// false, then the data will be used that one time and not saved.
// In that case, the handler will be invoked again if the stream
// data is accessed another time. Writing a handler that sets
// persist to true essentially allows delaying the computation of
// the stream data, while setting it to false reduces the amount
// of memory that is used.
QPDF_DLL
void replaceStreamData(PointerHolder<StreamDataHandler> dh);
// return 0 for direct objects
QPDF_DLL
int getObjectID() const;

View File

@ -319,6 +319,15 @@ QPDFObjectHandle::removeKey(std::string const& key)
return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->removeKey(key);
}
void
QPDFObjectHandle::replaceOrRemoveKey(std::string const& key,
QPDFObjectHandle value)
{
assertType("Dictionary", isDictionary());
return dynamic_cast<QPDF_Dictionary*>(
obj.getPointer())->replaceOrRemoveKey(key, value);
}
// Stream accessors
QPDFObjectHandle
QPDFObjectHandle::getDict()
@ -343,6 +352,23 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
p, filter, normalize, compress);
}
void
QPDFObjectHandle::replaceStreamData(PointerHolder<Buffer> data,
QPDFObjectHandle filter,
QPDFObjectHandle decode_parms)
{
assertType("Stream", isStream());
dynamic_cast<QPDF_Stream*>(obj.getPointer())->replaceStreamData(
data, filter, decode_parms);
}
void
QPDFObjectHandle::replaceStreamData(PointerHolder<StreamDataHandler> dh)
{
assertType("Stream", isStream());
dynamic_cast<QPDF_Stream*>(obj.getPointer())->replaceStreamData(dh);
}
int
QPDFObjectHandle::getObjectID() const
{

View File

@ -92,3 +92,17 @@ QPDF_Dictionary::removeKey(std::string const& key)
// no-op if key does not exist
this->items.erase(key);
}
void
QPDF_Dictionary::replaceOrRemoveKey(std::string const& key,
QPDFObjectHandle value)
{
if (value.isNull())
{
removeKey(key);
}
else
{
replaceKey(key, value);
}
}

View File

@ -319,9 +319,30 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
}
}
// XXX handle stream_data and stream_data_handler
QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
this->offset, this->length,
this->stream_dict, pipeline);
return filter;
}
void
QPDF_Stream::replaceStreamData(PointerHolder<Buffer> data,
QPDFObjectHandle filter,
QPDFObjectHandle decode_parms)
{
this->stream_data = data;
this->stream_dict.replaceOrRemoveKey("/Filter", filter);
this->stream_dict.replaceOrRemoveKey("/DecodeParms", decode_parms);
this->stream_dict.replaceKey("/Length",
QPDFObjectHandle::newInteger(
data.getPointer()->getSize()));
}
void
QPDF_Stream::replaceStreamData(
PointerHolder<QPDFObjectHandle::StreamDataHandler> dh)
{
this->stream_data_handler = dh;
}

View File

@ -26,6 +26,8 @@ class QPDF_Dictionary: public QPDFObject
void replaceKey(std::string const& key, QPDFObjectHandle const&);
// Remove key, doing nothing if key does not exist
void removeKey(std::string const& key);
// If object is null, replace key; otherwise, remove key
void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle);
protected:
virtual void releaseResolved();

View File

@ -18,24 +18,28 @@ class QPDF_Stream: public QPDFObject
virtual std::string unparse();
QPDFObjectHandle getDict() const;
// See comments in QPDFObjectHandle.hh
// See comments in QPDFObjectHandle.hh for these methods.
bool pipeStreamData(Pipeline*, bool filter,
bool normalize, bool compress);
// See comments in QPDFObjectHandle.hh
PointerHolder<Buffer> getStreamData();
void replaceStreamData(PointerHolder<Buffer> data,
QPDFObjectHandle filter,
QPDFObjectHandle decode_parms);
void replaceStreamData(
PointerHolder<QPDFObjectHandle::StreamDataHandler> dh);
private:
bool filterable(std::vector<std::string>& filters,
int& predictor, int& columns, bool& early_code_change);
QPDF* qpdf;
int objid;
int generation;
QPDFObjectHandle stream_dict;
off_t offset;
int length;
PointerHolder<QPDFObjectHandle::StreamDataHandler> stream_data_handler;
PointerHolder<Buffer> stream_data;
};
#endif // __QPDF_STREAM_HH__