Listing 1: dbstruct.cpp — A program demonstrating use of the persistence library

#include <UIOObj.h>  // TIOObjectBase, TIOObject<T>
#include <cstring.h>

// global variables
fstream* pfstream;  // disk file stream

// example "simple object classes"

struct X {
   int i;
   X (int _i = 0) : i(_i) {}    // is also default ctor...
};
class Y {
   public:
     double d[2];               // C arrays are OK
};
class XY: public X, public Y {
   public: XY(X _x=X(), Y _y=Y()): X(_x), Y(_y) {}
};

//---------------------------------------------------------------
// initialization
void init(char * filename)
{
   // open file, ios::binary!
   // ios::app to append new objects to existing file
    
   pfstream = new fstream(filename,
                     ios::in | ios::app | ios::binary);
   // clears registered classes, not really needed here,
   // but good habit

   TIOObjectBase::reset();

   // "Register" ALL classes that MIGHT BE in FILE INPUT

   TIOObject<X>::Register();
   TIOObject<Y>::Register();
   TIOObject<XY>::Register();
}

//---------------------------------------------------------------
void writeFile()        // OUTPUTS OBJECTS TO DISK FILE
{
   X x(10);                   // "detailed" way to write
   TIOObject<X> ioo(x);       // ctor
   ioo.write(*pfstream);      // and write. . .

   TIOObject<X>(X(20)).write(*pfstream); //  "all in one"
                                         //  construct and write

   Y y = { {1.2, 3.4} };
   TIOObject<Y>(y).write(*pfstream);

   x.i = 30;
   TIOObject<X>(x).write(*pfstream);

   TIOObject<XY> (XY(x,y)).write(*pfstream);
}

//--------------------------------------------------------------------
// OBJECT INPUT AND USEvoid useFile()
{
   // go file begin
   pfstream->rdbuf()->seekoff(0, ios::beg, ios::in);
   TIOObjectBase* pIOObjectBase;      // holds file input

   // the read-process loop
   while(true) {        // exits on end of file or exception
      try {             // Enclose input in try catch block !
          pIOObjectBase =
               TIOObjectBase::Create(*pfstream);
      }
      catch (const TIOObjectBase::EEof* )       // OK, end of file
      {
         cout << "End of Data" << endl;
         return;
      }
      // probably class name not registered?
      catch (const TIOObjectBase::EUnknownClass* e)
      {
         cout  << "error: " << e->mess.c_str() // offending name
               << " is unknown object type"    // is displayed
               << endl;
         return;
      }
      // *** bad news ***
      catch (const TIOObjectBase::exception* e) {
         cout << "error: " << e->mess.c_str() << endl
              << "file, line: "
              << __throwFileName << ", " << __throwLineNumber
              << endl;
         return;
      }
      // *** worse news ***
      catch (...)   {
         cout << "error: unknown exception thrown at " << endl
              << __throwFileName << ", " << __throwLineNumber
              << endl;
         return;
      }

      // pIOObjectBase has valid object, find type and process
      // T* TIOObject<T>::PtrData(TIOObjectBase*) returns:
      //     0 if pIOObjectBase is not a TIOObject<T>*
      //     a T* if OK

      if ( X* p = TIOObject<X>::PtrData(pIOObjectBase) ) {
         cout << "read an X. i = " << p->i << endl;
      }
      if ( Y* p = TIOObject<Y>::PtrData(pIOObjectBase) ) {
         cout << "read a Y. d[0], d[1] = "
              << p->d[0] <<",  "<< p->d[1] << endl;
      }
      if ( XY* p = TIOObject <XY>::PtrData(pIOObjectBase) ) {
         cout << "read a " << pIOObjectBase->name() 
              << " d[0], d[1] = " << p->d[0] <<",  "
              << p->d[1] << endl;
      }
      delete pIOObjectBase;
   } // end while(true);
}   // end useFile()

//---------------------------------------------------------------
//                         MAIN
//---------------------------------------------------------------
// usage dbstruct filename  r|w|rw
// r for read, w write or rw for write and read
int main (int argc, char* argv[])
{
   char c[1];
   if (argc < 3) {
      cout << "usage filename r|w|rw" << endl;
      cin.getline(c, 2);
      return 0;
   }
   else
      init(argv[1]);      // initialize
   if ( (strcmp(argv[2], "w")==0) || (strcmp(argv[2], "rw")==0) )
      writeFile();        // write objects to disk file
   if ( (strcmp(argv[2], "r")==0) || (strcmp(argv[2], "rw") == 0))
      useFile();          // read and use objects in file 

   // CLOSING PROGRAM
   delete pfstream;
   TIOObjectBase::reset(); // don't forget, memory leak...
   cout << "end of program, press newline ";
   cin.getline(c, 2);
   return 1;
}

//End of File