The dump operation is controlled by an object of type dump_context
which is defined
in persistent_contexts.hpp.
class stlplus::dump_context { public: // constructor dump_context(std::ostream& device, unsigned char version = PersistentVersion); ~dump_context(void); // low level output used to dump a byte void put(unsigned char data); // 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 put
method. 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.
A restore operation is controlled by a restore_context
object.
class restore_context { public: ////////////////////////////////////////////////////////////////////////////// // constructor restore_context(std::istream& device); ~restore_context(void); // low level input used to restore a byte int get(void); // 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; }; #endif
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.
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.