The Persistence I/O Infrastructure

Dump Context

The dump operation is controlled by an object of type dump_context which is defined in persistent_contexts.hpp.

class stlplus::dump_context
  // constructor
  dump_context(std::ostream& device, unsigned char version = PersistentVersion) throw(persistent_dump_failed);

  // low level output used to dump a byte
  void put(unsigned char data) throw(persistent_dump_failed);

  // access the device, for example to check the error status
  const std::ostream& device(void) const;

  // recover the version number of the dumped output
  unsigned char version(void) const;

A dump_context is initialised with an output device (any derivative of ostream) and is then passed down through the hierarchy of dump routines. At the end of the dump, the output device can be checked to see if an output error occurred. Here's a typical example of how to dump a data structure:

std::ofstream output(filename.c_str(), std::ios_base::out | std::ios_base::binary);
dump_context dumper(output);
dump(dumper, data);

In this example, you can see how an output file is created using IOStream. Note that the device must be in binary mode. Then the dump_context object is initialised with this output device. Then the dump function for the data structure is called. The output device should be closed, but this will be done by its destructor anyway.

Be careful however to ensure that binary mode is used if you transmit dumped data over networks - some programs (such as FTP) may try to convert data that looks like line endings to the 'correct' form for the operating system - corrupting the persistent data irretrievably.

Any dump operation, including the construction of the context, can throw an stlplus::persistent_dump_failed exception. Typically this will be because the write to the output file failed.

The constructor can fail because the context writes a small amount of internally-required data to the file before the dump starts, so if the writing of this data fails the exception will be thrown.

The persistence routines write data using the putmethod. However, you will rarely if ever call this yourself, instead you will call the various dump functions that are defined in the rest of the library. The idea is that you define the dump routine for your data structure in terms of the dump routines for the elements of that data structure, recursively.

Most of the rest of the class is concerned with declaring support routines for the persistence of polymorphic types. Their description will be deferred to the relevant section.

Restore Context

A restore operation is controlled by a restore_context object.

class restore_context

  // constructor
  restore_context(std::istream& device) throw(persistent_restore_failed);

  // low level input used to restore a byte
  int get(void) throw(persistent_restore_failed);

  // access the device, for example to check the error status
  const std::istream& device(void) const;

  // access the version number of the input being restored
  unsigned char version(void) const;

This is initialised with an input IOStream device. Here's an example of how to restore a data structure:

std::ifstream input(filename.c_str(), std::ios_base::in | std::ios_base::binary);
restore_context restorer(input);
restore(restorer, data);

The TextIO device must be in binary mode for persistence to work correctly.

Persistence Functions

The actual dump/restore of your data structure is performed by dump/restore functions which are built up from the persistence library routines. The following pages describe the various sets of functions that are available. The final page shows how to put them together.