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,6 +152,9 @@ class QPDFObjectHandle
152 // Remove key, doing nothing if key does not exist 152 // Remove key, doing nothing if key does not exist
153 QPDF_DLL 153 QPDF_DLL
154 void removeKey(std::string const& key); 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 // Methods for stream objects 159 // Methods for stream objects
157 QPDF_DLL 160 QPDF_DLL
@@ -183,6 +186,64 @@ class QPDFObjectHandle @@ -183,6 +186,64 @@ class QPDFObjectHandle
183 bool pipeStreamData(Pipeline*, bool filter, 186 bool pipeStreamData(Pipeline*, bool filter,
184 bool normalize, bool compress); 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 // return 0 for direct objects 247 // return 0 for direct objects
187 QPDF_DLL 248 QPDF_DLL
188 int getObjectID() const; 249 int getObjectID() const;
libqpdf/QPDFObjectHandle.cc
@@ -319,6 +319,15 @@ QPDFObjectHandle::removeKey(std::string const&amp; key) @@ -319,6 +319,15 @@ QPDFObjectHandle::removeKey(std::string const&amp; key)
319 return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->removeKey(key); 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 // Stream accessors 331 // Stream accessors
323 QPDFObjectHandle 332 QPDFObjectHandle
324 QPDFObjectHandle::getDict() 333 QPDFObjectHandle::getDict()
@@ -343,6 +352,23 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter, @@ -343,6 +352,23 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
343 p, filter, normalize, compress); 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 int 372 int
347 QPDFObjectHandle::getObjectID() const 373 QPDFObjectHandle::getObjectID() const
348 { 374 {
libqpdf/QPDF_Dictionary.cc
@@ -92,3 +92,17 @@ QPDF_Dictionary::removeKey(std::string const&amp; key) @@ -92,3 +92,17 @@ QPDF_Dictionary::removeKey(std::string const&amp; key)
92 // no-op if key does not exist 92 // no-op if key does not exist
93 this->items.erase(key); 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,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 QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation, 323 QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
323 this->offset, this->length, 324 this->offset, this->length,
324 this->stream_dict, pipeline); 325 this->stream_dict, pipeline);
325 326
326 return filter; 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,6 +26,8 @@ class QPDF_Dictionary: public QPDFObject
26 void replaceKey(std::string const& key, QPDFObjectHandle const&); 26 void replaceKey(std::string const& key, QPDFObjectHandle const&);
27 // Remove key, doing nothing if key does not exist 27 // Remove key, doing nothing if key does not exist
28 void removeKey(std::string const& key); 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 protected: 32 protected:
31 virtual void releaseResolved(); 33 virtual void releaseResolved();
libqpdf/qpdf/QPDF_Stream.hh
@@ -18,24 +18,28 @@ class QPDF_Stream: public QPDFObject @@ -18,24 +18,28 @@ class QPDF_Stream: public QPDFObject
18 virtual std::string unparse(); 18 virtual std::string unparse();
19 QPDFObjectHandle getDict() const; 19 QPDFObjectHandle getDict() const;
20 20
21 - // See comments in QPDFObjectHandle.hh 21 + // See comments in QPDFObjectHandle.hh for these methods.
22 bool pipeStreamData(Pipeline*, bool filter, 22 bool pipeStreamData(Pipeline*, bool filter,
23 bool normalize, bool compress); 23 bool normalize, bool compress);
24 -  
25 - // See comments in QPDFObjectHandle.hh  
26 PointerHolder<Buffer> getStreamData(); 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 private: 31 private:
29 bool filterable(std::vector<std::string>& filters, 32 bool filterable(std::vector<std::string>& filters,
30 int& predictor, int& columns, bool& early_code_change); 33 int& predictor, int& columns, bool& early_code_change);
31 34
32 -  
33 QPDF* qpdf; 35 QPDF* qpdf;
34 int objid; 36 int objid;
35 int generation; 37 int generation;
36 QPDFObjectHandle stream_dict; 38 QPDFObjectHandle stream_dict;
37 off_t offset; 39 off_t offset;
38 int length; 40 int length;
  41 + PointerHolder<QPDFObjectHandle::StreamDataHandler> stream_data_handler;
  42 + PointerHolder<Buffer> stream_data;
39 }; 43 };
40 44
41 #endif // __QPDF_STREAM_HH__ 45 #endif // __QPDF_STREAM_HH__