Using Persistent Streams With Doc/View

Date: 27 July 1997
Author: Leo Goodstadt

The streams which come with the OWL Document / View architecture are standard c++ iostreams. In other words, if you write a short integer of 500 to a stream obtained via TDocument::OutStream, the characters 0x35 0x30 0x30 ('5','0','0') will be written to the stream followed by a separator, instead of just 0x01 0xf4. Often you may prefer the more efficient representation. This is an even more significant consideration when streaming floating point numbers. Borland persistent streams also allow you to stream and recreate complete objects with versioning and resolution of pointers etc. For more information on Borland persistent streams please refer to the documentation.

There are two ways to use the Borland persistent streaming mechanisms with the OWL Document / View architecture.

The first involves modification of the source code.

The second does not :->

 


  //  ----- ---------
  //  class TInStream - base class for input streams
  //
#if defined(USE_DOCUMENT_STREAMS)
  class _OWLCLASS_RTL TInStream : public TStream, public ipstream {
  public:
  TInStream(TDocument& doc, const char far* name, int mode)
  : TStream(doc, name, mode), ipstream() {}
#else
  class _OWLCLASS_RTL TInStream : public TStream, public istream {
  public:
  TInStream(TDocument& doc, const char far* name, int mode)
  : TStream(doc, name, mode), istream() {}
#endif
  };

  //
  //  class TOutStream - base class for output streams
  //  ----- ---------
  //
#if defined(USE_DOCUMENT_STREAMS)
  class _OWLCLASS_RTL TOutStream : public TStream, public opstream {
  public:
  TOutStream(TDocument& doc, const char far* name, int mode)
  : TStream(doc, name, mode), opstream() {}
#else
  class _OWLCLASS_RTL TOutStream : public TStream, public ostream {
  public:
  TOutStream(TDocument& doc, const char far* name, int mode)
  : TStream(doc, name, mode), ostream() {}
#endif
  };

Change the declaration of TStorageStreamBase in stgdoc.cpp

  //
  //  class TStorageStreamBase
  //  ----- ------------------
  //
#if defined(USE_DOCUMENT_STREAMS)
  class _OWLCLASS_RTL TStorageStreamBase : virtual public pstream {
#else
  class _OWLCLASS_RTL TStorageStreamBase : virtual public ios {
#endif
 

Change the initiation in the constructor of TstorageStreamBase in stgdoc.cpp

  TStorageStreamBase::TStorageStreamBase(IStorage& stg, const char far* name, int mode)
  :
    buf()
  {
#if defined(USE_DOCUMENT_STREAMS)
    pstream::init(&buf);
#else
    ios::init(&buf);
#endif

The following code is standard streaming code modified from the OWL tutorial.
To use persistent streams, use the following code with
USE_DOCUMENT_STREAMS defined. The lines highlighted in blue add persistent streaming.

 

bool TYourDocument::Commit(bool force)
{
  TOleDocument::Commit(force);

  // use TPointer to make sure stream is deleted on exit from this function
  #if defined(USE_DOCUMENT_STREAMS)
  TPointer<TOutStream> outstrm = OutStream(ofWrite | ofBinary);	
  TPointer<opstream> os = new opstream(outstrm->rdbuf());
  #elseif
  TPointer<TOutStream> os = OutStream(ofWrite);	
  #endif
  if (!os)
    return false;

  // Write a test integer
  int Test = 500;
  *os << Test;

  #if defined(USE_DOCUMENT_STREAMS)
  os.flush();
  #endif

  //
  // Commit the storage if it was opened in transacted mode
  TOleDocument::CommitTransactedStorage();
  SetDirty(false);

  return true;
}

bool TYourDocument::Open(int mode, const char far* path)
{
  TOleDocument::Open(mode, path);   // normally path should be null
  #if defined(USE_DOCUMENT_STREAMS)
  TPointer<TInStream> isstrm = InStream(ofRead | ofBinary);	
  TPointer<ipstream> is = new ipstream(isstrm->rdbuf());
  #elseif
  TPointer<TInStream> is = InStream(ofRead);
  #endif
  if (!is)
    return false;

  // Read a test integer
  int Test;
  *is >> Test;

}