Tuesday 1 September 2009

Boost Serilization XML and deeper hierarchies

I've been playing with serializing to XML and what to do with inheritance that has 3 levels. My hierarchy consists of Actor < Crit < Predator. In the serialization code, class Predator just refers to class Crit and that's it.

In main.cpp:
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
#include <iostream>

using namespace
boost;
using namespace
std;

class
Actor
{

public
:
Actor( void ) {}
Actor( char gender )
:
gender( gender )
{}

virtual
~Actor() {}
char
Gender( void ) const { return gender; }
private
:
friend class
boost::serialization::access;
template
<class Archive>
void
serialize(Archive & ar, const unsigned int version)
{

ar & BOOST_SERIALIZATION_NVP( gender );
}

char
gender;
};


class
Crit: public Actor
{

public
:
Crit( void ) {}
Crit( int age )
:
age( age )
{
}

int
Age( void ) const { return age; }
private
:
friend class
boost::serialization::access;
template
<class Archive>
void
serialize(Archive & ar, const unsigned int version)
{

ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( Actor );
ar & BOOST_SERIALIZATION_NVP( age );
}

int
age;
};


BOOST_CLASS_EXPORT_GUID( Crit, "Crit")

class
Predator: public Crit
{

public
:
Predator( void ) {}
Predator( string name )
:
name( name )
{
}

string Name( void ) const { return name; }
private
:
friend class
boost::serialization::access;
template
<class Archive>
void
serialize(Archive & ar, const unsigned int version)
{

ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( Crit );
ar & BOOST_SERIALIZATION_NVP( name );
}

string name;
};


BOOST_CLASS_EXPORT_GUID( Predator, "Predator")

class
Food: public Actor
{

public
:
Food( void ) {}
Food( int energy )
:
energy( energy )
{
}

int
Energy( void ) const { return energy; }
private
:
friend class
boost::serialization::access;
template
<class Archive>
void
serialize(Archive & ar, const unsigned int version)
{

ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( Actor );
ar & BOOST_SERIALIZATION_NVP( energy );
}

int
energy;
};


BOOST_CLASS_EXPORT_GUID( Food, "Food")

template
< typename T >
void
save( const T& data, string filename )
{

ofstream ofs( filename.c_str() );
boost::archive::xml_oarchive oa( ofs );
oa & BOOST_SERIALIZATION_NVP( data );
}


template
< typename T >
void
load( T& data, string filename )
{

ifstream ofs( filename.c_str() );
boost::archive::xml_iarchive ia( ofs );
ia & BOOST_SERIALIZATION_NVP( data );
}


void
TestAlpha( void )
{

shared_ptr< Crit > critAlpha( new Crit( 18 ) );
shared_ptr< Crit > critBravo( new Crit( 19 ) );
shared_ptr< Predator > predAlpha( new Predator( "Bob" ) );
shared_ptr< Predator > predBravo( new Predator( "Jane" ) );
shared_ptr< Food > foodAlpha( new Food( 20 ) );
shared_ptr< Food > foodBravo( new Food( 21 ) );

vector< shared_ptr< Actor > > conAlpha;
vector< shared_ptr< Actor > > conBravo;

conAlpha.push_back( critAlpha );
conAlpha.push_back( foodAlpha );
conAlpha.push_back( predAlpha );

// save
string filename = "sav.sav";
save( conAlpha, filename );

// test
assert( critBravo->Age() == 19 );
assert( foodBravo->Energy() == 21 );
assert( predBravo->Name() == "Jane" );

// load
load( conBravo, filename );

// test
critBravo = dynamic_pointer_cast< Crit >( conBravo[ 0 ] );
assert( critBravo->Age() == 18 );
foodBravo = dynamic_pointer_cast< Food >( conBravo[ 1 ] );
assert( foodBravo->Energy() == 20 );
predBravo = dynamic_pointer_cast< Predator >( conBravo[ 2 ] );
assert( predBravo->Name() == "Bob" );
}


int
main( int argc, const char* argv[] )
{

TestAlpha();
return
EXIT_SUCCESS;
}

In Makefile (remember to put a real tab before where it says 'g++'):
all:
g++ -g -Wall testBoostSerializationInheritance.cpp -lboost_serialization

No comments:

Post a Comment