mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
ready to implement replacement stream data
git-svn-id: svn+q:///qpdf/trunk@987 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
parent
ab5a01c64e
commit
9a06fc541c
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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__
|
||||
|
Loading…
Reference in New Issue
Block a user