Commit 9a06fc541ce00361f12f6231b2f7556615cbccb7

Authored by Jay Berkenbilt
1 parent ab5a01c6

ready to implement replacement stream data

git-svn-id: svn+q:///qpdf/trunk@987 71b93d88-0707-0410-a8cf-f5a4172ac649
include/qpdf/QPDFObjectHandle.hh
... ... @@ -152,6 +152,9 @@ class QPDFObjectHandle
152 152 // Remove key, doing nothing if key does not exist
153 153 QPDF_DLL
154 154 void removeKey(std::string const& key);
  155 + // If the object is null, remove the key. Otherwise, replace it.
  156 + QPDF_DLL
  157 + void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle);
155 158  
156 159 // Methods for stream objects
157 160 QPDF_DLL
... ... @@ -183,6 +186,64 @@ class QPDFObjectHandle
183 186 bool pipeStreamData(Pipeline*, bool filter,
184 187 bool normalize, bool compress);
185 188  
  189 + // Replace this stream's stream data with the given data buffer,
  190 + // and replace the /Filter and /DecodeParms keys in the stream
  191 + // dictionary with the given values. (If either value is empty,
  192 + // the corresponding key is removed.) The stream's /Length key is
  193 + // replaced with the length of the data buffer. The stream is
  194 + // interpreted as if the data read from the file, after any
  195 + // decryption filters have been applied, is as presented.
  196 + QPDF_DLL
  197 + void replaceStreamData(PointerHolder<Buffer> data,
  198 + QPDFObjectHandle filter,
  199 + QPDFObjectHandle decode_parms);
  200 + class StreamDataHandler
  201 + {
  202 + public:
  203 + QPDF_DLL
  204 + virtual ~StreamDataHandler()
  205 + {
  206 + }
  207 +
  208 + // See replaceStreamData(StreamDataHandler) below for a
  209 + // description of how to override this function.
  210 + virtual void
  211 + replaceStreamData(Buffer const& in_data,
  212 + std::string const& in_filter,
  213 + std::string const& in_decode_parms,
  214 + bool filtered,
  215 + Buffer& out_data,
  216 + std::string& out_filter,
  217 + std::string& out_decode_parms,
  218 + bool& persist) = 0;
  219 + };
  220 + // Provide a hook for doing dynamic replacement of the stream's
  221 + // data. When the stream's data is accessed either with
  222 + // pipeStreamData or with getStreamData, if the stream doesn't
  223 + // already have replacement data, an attempt is first made to
  224 + // filter the stream's original data. If the attempt is
  225 + // successful, the stream's filtered original data is passed to
  226 + // the handler as in_data, and filtered is true. If the original
  227 + // data cannot be processed, then in_data is the original raw data
  228 + // (after any decryption filters have been applied) and filtered
  229 + // is false. If the original input data has no filters applied,
  230 + // the filtered is true. This way, if filtered is true, the
  231 + // caller knows that in_data contains the fully filtered data.
  232 + // The handler then provides replacement data, /Filter, and
  233 + // /DecodeParms (handled is in the simpler form of
  234 + // replaceStreamData above). If the persist argument is set to
  235 + // true, then the replacement data is stored in the stream object
  236 + // where it will be used on subsequent attempts to retrieve the
  237 + // data (rather than calling the handler). If persist is set to
  238 + // false, then the data will be used that one time and not saved.
  239 + // In that case, the handler will be invoked again if the stream
  240 + // data is accessed another time. Writing a handler that sets
  241 + // persist to true essentially allows delaying the computation of
  242 + // the stream data, while setting it to false reduces the amount
  243 + // of memory that is used.
  244 + QPDF_DLL
  245 + void replaceStreamData(PointerHolder<StreamDataHandler> dh);
  246 +
186 247 // return 0 for direct objects
187 248 QPDF_DLL
188 249 int getObjectID() const;
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -319,6 +319,15 @@ QPDFObjectHandle::removeKey(std::string const&amp; key)
319 319 return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->removeKey(key);
320 320 }
321 321  
  322 +void
  323 +QPDFObjectHandle::replaceOrRemoveKey(std::string const& key,
  324 + QPDFObjectHandle value)
  325 +{
  326 + assertType("Dictionary", isDictionary());
  327 + return dynamic_cast<QPDF_Dictionary*>(
  328 + obj.getPointer())->replaceOrRemoveKey(key, value);
  329 +}
  330 +
322 331 // Stream accessors
323 332 QPDFObjectHandle
324 333 QPDFObjectHandle::getDict()
... ... @@ -343,6 +352,23 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
343 352 p, filter, normalize, compress);
344 353 }
345 354  
  355 +void
  356 +QPDFObjectHandle::replaceStreamData(PointerHolder<Buffer> data,
  357 + QPDFObjectHandle filter,
  358 + QPDFObjectHandle decode_parms)
  359 +{
  360 + assertType("Stream", isStream());
  361 + dynamic_cast<QPDF_Stream*>(obj.getPointer())->replaceStreamData(
  362 + data, filter, decode_parms);
  363 +}
  364 +
  365 +void
  366 +QPDFObjectHandle::replaceStreamData(PointerHolder<StreamDataHandler> dh)
  367 +{
  368 + assertType("Stream", isStream());
  369 + dynamic_cast<QPDF_Stream*>(obj.getPointer())->replaceStreamData(dh);
  370 +}
  371 +
346 372 int
347 373 QPDFObjectHandle::getObjectID() const
348 374 {
... ...
libqpdf/QPDF_Dictionary.cc
... ... @@ -92,3 +92,17 @@ QPDF_Dictionary::removeKey(std::string const&amp; key)
92 92 // no-op if key does not exist
93 93 this->items.erase(key);
94 94 }
  95 +
  96 +void
  97 +QPDF_Dictionary::replaceOrRemoveKey(std::string const& key,
  98 + QPDFObjectHandle value)
  99 +{
  100 + if (value.isNull())
  101 + {
  102 + removeKey(key);
  103 + }
  104 + else
  105 + {
  106 + replaceKey(key, value);
  107 + }
  108 +}
... ...
libqpdf/QPDF_Stream.cc
... ... @@ -319,9 +319,30 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
319 319 }
320 320 }
321 321  
  322 + // XXX handle stream_data and stream_data_handler
322 323 QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
323 324 this->offset, this->length,
324 325 this->stream_dict, pipeline);
325 326  
326 327 return filter;
327 328 }
  329 +
  330 +void
  331 +QPDF_Stream::replaceStreamData(PointerHolder<Buffer> data,
  332 + QPDFObjectHandle filter,
  333 + QPDFObjectHandle decode_parms)
  334 +{
  335 + this->stream_data = data;
  336 + this->stream_dict.replaceOrRemoveKey("/Filter", filter);
  337 + this->stream_dict.replaceOrRemoveKey("/DecodeParms", decode_parms);
  338 + this->stream_dict.replaceKey("/Length",
  339 + QPDFObjectHandle::newInteger(
  340 + data.getPointer()->getSize()));
  341 +}
  342 +
  343 +void
  344 +QPDF_Stream::replaceStreamData(
  345 + PointerHolder<QPDFObjectHandle::StreamDataHandler> dh)
  346 +{
  347 + this->stream_data_handler = dh;
  348 +}
... ...
libqpdf/qpdf/QPDF_Dictionary.hh
... ... @@ -26,6 +26,8 @@ class QPDF_Dictionary: public QPDFObject
26 26 void replaceKey(std::string const& key, QPDFObjectHandle const&);
27 27 // Remove key, doing nothing if key does not exist
28 28 void removeKey(std::string const& key);
  29 + // If object is null, replace key; otherwise, remove key
  30 + void replaceOrRemoveKey(std::string const& key, QPDFObjectHandle);
29 31  
30 32 protected:
31 33 virtual void releaseResolved();
... ...
libqpdf/qpdf/QPDF_Stream.hh
... ... @@ -18,24 +18,28 @@ class QPDF_Stream: public QPDFObject
18 18 virtual std::string unparse();
19 19 QPDFObjectHandle getDict() const;
20 20  
21   - // See comments in QPDFObjectHandle.hh
  21 + // See comments in QPDFObjectHandle.hh for these methods.
22 22 bool pipeStreamData(Pipeline*, bool filter,
23 23 bool normalize, bool compress);
24   -
25   - // See comments in QPDFObjectHandle.hh
26 24 PointerHolder<Buffer> getStreamData();
  25 + void replaceStreamData(PointerHolder<Buffer> data,
  26 + QPDFObjectHandle filter,
  27 + QPDFObjectHandle decode_parms);
  28 + void replaceStreamData(
  29 + PointerHolder<QPDFObjectHandle::StreamDataHandler> dh);
27 30  
28 31 private:
29 32 bool filterable(std::vector<std::string>& filters,
30 33 int& predictor, int& columns, bool& early_code_change);
31 34  
32   -
33 35 QPDF* qpdf;
34 36 int objid;
35 37 int generation;
36 38 QPDFObjectHandle stream_dict;
37 39 off_t offset;
38 40 int length;
  41 + PointerHolder<QPDFObjectHandle::StreamDataHandler> stream_data_handler;
  42 + PointerHolder<Buffer> stream_data;
39 43 };
40 44  
41 45 #endif // __QPDF_STREAM_HH__
... ...