test-serialization.C

Go to the documentation of this file.
00001 /*!@file Simulation/test-serialization.C simple test code for serialization of SimEvent */
00002 
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00006 // by the University of Southern California (USC) and the iLab at USC.  //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Simulation/SimEvent.H $
00036 // $Id: SimEvent.H 9031 2007-11-23 10:54:03Z siagian $
00037 //
00038 
00039 #include "Util/log.H"
00040 
00041 #ifndef HAVE_BOOST_SERIALIZATION
00042 
00043 int main(int argc, const char **argv)
00044 {
00045   LFATAL("You need Boost::Serialization installed on your system for this program to work");
00046   return 1;
00047 }
00048 
00049 #else
00050 
00051 // include headers that implement an archive in simple text format
00052 #include <boost/archive/text_oarchive.hpp>
00053 #include <boost/archive/text_iarchive.hpp>
00054 #include <boost/serialization/access.hpp> 
00055 #include <boost/serialization/config.hpp>
00056 #include <boost/serialization/vector.hpp>
00057 
00058 #include <fstream>
00059 
00060 typedef unsigned char byte;
00061 
00062 // this code derived from http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/index.html
00063 
00064 // ######################################################################
00065 // ######################################################################
00066 // Straight-up code for a serializable class and a derived class:
00067 // ######################################################################
00068 // ######################################################################
00069 
00070 // ######################################################################
00071 // SimModule is used in the constructor of SimEvent, here we just fake it
00072 class SimModule {
00073 };
00074 
00075 // ######################################################################
00076 // Base class, contains no data
00077 // this will be provided in the systemwide definition of SimEvent
00078 class SimEvent {
00079 public:
00080   SimEvent(SimModule* src = 0) { }
00081 
00082   virtual ~SimEvent() { }
00083 
00084   inline std::string toString() const { return std::string("define me as in old SimEvent def"); }
00085 
00086 private:
00087   friend class boost::serialization::access;
00088   template<class Archive> inline void serialize(Archive& ar, const unsigned int version) { }
00089 };
00090 
00091 BOOST_CLASS_VERSION(SimEvent, 0); // bump this whenever you change the class' serializable data members
00092 
00093 // ######################################################################
00094 // Class derived directly from SimEvent, adds two data members, one int and one float
00095 class MySimEvent : public SimEvent {
00096 public:
00097   MySimEvent(SimModule* src = 0) { }
00098 
00099   MySimEvent(SimModule* src__, const int idata__, const float fdata__) :
00100     SimEvent(src__), idata_(idata__), fdata_(fdata__) { }
00101 
00102   virtual ~MySimEvent() { }
00103 
00104   int& idata() { return idata_; }
00105   float& fdata() { return fdata_; }
00106 
00107   const int& idata() const { return idata_; }
00108   const float& fdata() const { return fdata_; }
00109 
00110 private:
00111   friend class boost::serialization::access;
00112 
00113   template<class Archive> void serialize(Archive& ar, const unsigned int version)
00114   {
00115     // serialize base class information:
00116     ar & boost::serialization::base_object<SimEvent>(*this);
00117 
00118     // and the new data from the derived class:
00119     ar & idata_;
00120     ar & fdata_;
00121   }
00122 
00123   int idata_; // some data member
00124   float fdata_; // some data member
00125 };
00126 
00127 BOOST_CLASS_VERSION(MySimEvent, 0); // bump this whenever you change the class' serializable data members
00128 
00129 
00130 // ######################################################################
00131 // Class further derived from the derived MySimEvent, adds yet more data members
00132 class DerSimEvent : public MySimEvent {
00133 public:
00134   DerSimEvent(SimModule* src = 0) { }
00135 
00136   DerSimEvent(SimModule* src__, const int idata__, const float fdata__,
00137               const std::string& sdata__, const std::vector<byte>& vdata__) :
00138     MySimEvent(src__, idata__, fdata__), sdata_(sdata__), vdata_(vdata__) { }
00139 
00140   virtual ~DerSimEvent() { }
00141 
00142   std::string& sdata() { return sdata_; }
00143   std::vector<byte>& vdata() { return vdata_; }
00144 
00145   const std::string& sdata() const { return sdata_; }
00146   const std::vector<byte>& vdata() const { return vdata_; }
00147 
00148 private:
00149   friend class boost::serialization::access;
00150 
00151   template<class Archive> void serialize(Archive& ar, const unsigned int version)
00152   {
00153     // serialize base class information:
00154     ar & boost::serialization::base_object<MySimEvent>(*this);
00155 
00156     // and the new data from the derived class:
00157     ar & sdata_;
00158     ar & vdata_;
00159   }
00160 
00161   std::string sdata_; // note: initialization will deep copy, in reality we will use shared_ptr
00162   std::vector<byte> vdata_;
00163 };
00164 
00165 BOOST_CLASS_VERSION(DerSimEvent, 0); // bump this whenever you change the class' serializable data members
00166 
00167 // ######################################################################
00168 // ######################################################################
00169 // Version with automatic creation of serialize()
00170 // ######################################################################
00171 // ######################################################################
00172 
00173 // **********************************************************************
00174 // ******************** INTERNALS:
00175 // **********************************************************************
00176 
00177 #include <boost/preprocessor/seq.hpp>
00178 #include <boost/preprocessor/arithmetic/add.hpp>
00179 #include <boost/preprocessor/comparison/equal.hpp>
00180 #include <boost/preprocessor/punctuation/comma.hpp>
00181 #include <boost/preprocessor/control/if.hpp>
00182 #include <boost/preprocessor/punctuation/paren.hpp>
00183 #include <boost/preprocessor/facilities/empty.hpp>
00184 
00185 // try: g++ -include config.h -E src/Simulation/test-serialization.C to see the generated source
00186 
00187 //! Root class for our SimEvent objects
00188 #define INVT_PP_SIMEVENT_ROOT_CLASS SimEvent
00189 
00190 //! Build our class variable's name from the named passed
00191 #define INVT_PP_SIMEVENT_VAR(V) BOOST_PP_CAT(V, _)
00192 
00193 //! Get elements of a tuple from our declaration list
00194 #define INVT_PP_SIMEVENT_ELEM_TYP(v) BOOST_PP_TUPLE_ELEM(2, 0, v)
00195 #define INVT_PP_SIMEVENT_ELEM_VAR(v) BOOST_PP_TUPLE_ELEM(2, 1, v)
00196 
00197 //! Declare a variable (use with BOOST_PP_SEQ_FOR_EACH)
00198 #define INVT_PP_SIMEVENT_DECLARE(r,x,val) INVT_PP_SIMEVENT_ELEM_TYP(val) \
00199   INVT_PP_SIMEVENT_VAR(INVT_PP_SIMEVENT_ELEM_VAR(val));                 \
00200   /**/
00201 
00202 //! Archive (serialization) action for a variable (use with BOOST_PP_SEQ_FOR_EACH) 
00203 #define INVT_PP_SIMEVENT_ARCHIVE(r,x,val) ar & INVT_PP_SIMEVENT_VAR(INVT_PP_SIMEVENT_ELEM_VAR(val));
00204 
00205 //! Access function for a variable (use with BOOST_PP_SEQ_FOR_EACH)
00206 #define INVT_PP_SIMEVENT_ACCESS(r,x,val)                                \
00207   inline INVT_PP_SIMEVENT_ELEM_TYP(val) & INVT_PP_SIMEVENT_ELEM_VAR(val)()     \
00208   { return INVT_PP_SIMEVENT_VAR(INVT_PP_SIMEVENT_ELEM_VAR(val)); }      \
00209   /**/
00210 
00211 //! Access function for a variable, const version (use with BOOST_PP_SEQ_FOR_EACH)
00212 #define INVT_PP_SIMEVENT_ACCESS_CONST(r,x,val)                          \
00213   inline const INVT_PP_SIMEVENT_ELEM_TYP(val)& INVT_PP_SIMEVENT_ELEM_VAR(val)() const \
00214   { return INVT_PP_SIMEVENT_VAR(INVT_PP_SIMEVENT_ELEM_VAR(val)); }      \
00215   /**/
00216 
00217 //! Some empty implementation of a function
00218 #define INVT_PP_SIMEVENT_EMPTY_IMPL { }
00219 
00220 //! Default constructor
00221 #define INVT_PP_SIMEVENT_DEFAULT_CONSTRUCTOR(CLASSNAME, BASECLASSNAME, CONSTR) \
00222   BOOST_PP_IF(BOOST_PP_EQUAL(CONSTR, 0), BOOST_PP_EMPTY(),              \
00223               CLASSNAME(SimModule* invt_pp_simevent_source = 0)         \
00224               BOOST_PP_IF(BOOST_PP_EQUAL(CONSTR, 1), ;,                 \
00225                           : BASECLASSNAME(invt_pp_simevent_source) INVT_PP_SIMEVENT_EMPTY_IMPL) ) \
00226 /**/
00227 
00228 //! Destructor
00229 #define INVT_PP_SIMEVENT_DESTRUCTOR(CLASSNAME, DESTR)                   \
00230   BOOST_PP_IF(BOOST_PP_EQUAL(DESTR, 0), BOOST_PP_EMPTY(),               \
00231               BOOST_PP_IF(BOOST_PP_EQUAL(DESTR, 1), virtual ~CLASSNAME();, \
00232                           virtual inline ~CLASSNAME() INVT_PP_SIMEVENT_EMPTY_IMPL) ) \
00233 /**/
00234 
00235 //! Serialization friend, to allow the boost-serializer to access our private serialize() function
00236 #define INVT_PP_SIMEVENT_SERIALIZATION_FRIEND friend class boost::serialization::access;
00237 
00238 //! Serialize function declaration and definition
00239 #define INVT_PP_SIMEVENT_SERIALIZE_FUNC(BASECLASSNAME, V)               \
00240   template<class Archive> inline void serialize(Archive& ar, const unsigned int version) \
00241   {                                                                     \
00242     ar & boost::serialization::base_object<BASECLASSNAME>(*this);       \
00243     BOOST_PP_SEQ_FOR_EACH(INVT_PP_SIMEVENT_ARCHIVE,,V)                  \
00244   }                                                                     \
00245 /**/
00246 
00247 //! toString function declaration
00248 #define INVT_PP_SIMEVENT_TOSTRING_DECL(BASECLASSNAME, TOSTR) \
00249     BOOST_PP_IF(BOOST_PP_EQUAL(TOSTR, 0), BOOST_PP_EMPTY(),             \
00250                 virtual std::string toString() const                    \
00251                 BOOST_PP_IF(BOOST_PP_EQUAL(TOSTR, 1), ;, { return BASECLASSNAME::toString(); } ) )
00252 /**/
00253 
00254 //! General class declaration
00255 #define INVT_PP_SIMEVENT_CLASSDECL(CLASSNAME, BASECLASSNAME, CLASSDECL, SERVERSION) \
00256   BOOST_PP_IF(BOOST_PP_EQUAL(CLASSDECL, 0), BOOST_PP_EMPTY(),           \
00257               class CLASSNAME;                                          \
00258               BOOST_CLASS_VERSION(CLASSNAME, SERVERSION);               \
00259               class CLASSNAME : public BASECLASSNAME { )                \
00260 /**/
00261 
00262 // **********************************************************************
00263 // ******************** USER MACROS:
00264 // **********************************************************************
00265 
00266 //! Class declaration for a SimEvent derived class
00267 /*! CLASSDECL = 0 (no class declaration, no opening brace), 1 (class decl + brace)
00268     CONSTR = 0 (no default constructor), 1 (declaration), 2 (decl + empty implementation)
00269     DESTR = 0 (no destructor), 1 (declaration), 2 (decl + empty implementation) 
00270     TOSTR = 0 (no toString() declaration), 1 (declaration), 2 (decl + empty implementation) */
00271 
00272 #define SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, BASECLASSNAME, V, CLASSDECL, CONSTR, DESTR, TOSTR, SERVERSION) \
00273   INVT_PP_SIMEVENT_CLASSDECL(CLASSNAME, BASECLASSNAME, CLASSDECL, SERVERSION) \
00274                                                                         \
00275   public:                                                               \
00276     INVT_PP_SIMEVENT_DEFAULT_CONSTRUCTOR(CLASSNAME, BASECLASSNAME, CONSTR) \
00277     INVT_PP_SIMEVENT_DESTRUCTOR(CLASSNAME, DESTR)                       \
00278     BOOST_PP_SEQ_FOR_EACH(INVT_PP_SIMEVENT_ACCESS,, V)                  \
00279     BOOST_PP_SEQ_FOR_EACH(INVT_PP_SIMEVENT_ACCESS_CONST,, V)            \
00280     INVT_PP_SIMEVENT_TOSTRING_DECL(BASECLASSNAME, TOSTR)                \
00281                                                                         \
00282   private:                                                              \
00283     BOOST_PP_SEQ_FOR_EACH(INVT_PP_SIMEVENT_DECLARE,, V)                 \
00284     INVT_PP_SIMEVENT_SERIALIZATION_FRIEND                               \
00285     INVT_PP_SIMEVENT_SERIALIZE_FUNC(BASECLASSNAME, V)                   \
00286   /**/
00287 
00288 // ##### Declare the class and define a bunch of things in it. Nice but screws up auto-indent in emacs
00289 #define SIMEVENT_CLASS_DECLARATION_TRIVIAL(CLASSNAME)                   \
00290   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, INVT_PP_SIMEVENT_ROOT_CLASS, , 1, 2, 2, 2, 0)
00291 
00292 #define SIMEVENT_CLASS_DECLARATION_SIMPLE(CLASSNAME, V)                 \
00293   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, INVT_PP_SIMEVENT_ROOT_CLASS, V, 1, 2, 2, 1, 0)
00294 
00295 #define SIMEVENT_CLASS_DECLARATION_BARE(CLASSNAME, BASECLASSNAME, V)    \
00296   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, BASECLASSNAME, V, 1, 0, 0, 0, 0)
00297 
00298 #define SIMEVENT_CLASS_DECLARATION(CLASSNAME, BASECLASSNAME, V, CONSTR, DESTR, TOSTR, SERVERSION) \
00299   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, BASECLASSNAME, V, 1, CONSTR, DESTR, TOSTR, SERVERSION) \
00300   /**/
00301 
00302 // ##### You declare the class manually (including opening brace), and here we just fill in the details
00303 #define SIMEVENT_CLASS_DEFINITION_TRIVIAL(CLASSNAME)                   \
00304   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, INVT_PP_SIMEVENT_ROOT_CLASS, , 0, 2, 2, 2, 0)
00305 
00306 #define SIMEVENT_CLASS_DEFINITION_SIMPLE(CLASSNAME, V)                 \
00307   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, INVT_PP_SIMEVENT_ROOT_CLASS, V, 0, 2, 2, 1, 0)
00308 
00309 #define SIMEVENT_CLASS_DEFINITION_BARE(CLASSNAME, BASECLASSNAME, V)     \
00310   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, BASECLASSNAME, V, 0, 0, 0, 0, 0)
00311 
00312 #define SIMEVENT_CLASS_DEFINITION(CLASSNAME, BASECLASSNAME, V, CONSTR, DESTR, TOSTR, SERVERSION) \
00313   SIMEVENT_CLASS_DECLARATION_INTERNAL(CLASSNAME, BASECLASSNAME, V, 0, CONSTR, DESTR, TOSTR, SERVERSION) \
00314   /**/
00315 
00316 
00317 // **********************************************************************
00318 // ******************** Examples:
00319 // **********************************************************************
00320 
00321 // ######################################################################
00322 SIMEVENT_CLASS_DECLARATION_TRIVIAL(TrivSimEvent)
00323   // could declare alternate (parameterized) constructors here
00324 
00325   // could declare member functions here
00326 
00327   // you should not declare data members here, all your data members should be serializable!
00328 };
00329 
00330 // ######################################################################
00331 SIMEVENT_CLASS_DECLARATION_SIMPLE( MySimEvent2,
00332                                    (( int, idata ))
00333                                    (( float, fdata )) )
00334 public:
00335   // could declare alternate (parameterized) constructors here, for example:
00336   MySimEvent2(SimModule* src__, const int idata__, const float fdata__) :
00337     SimEvent(src__), idata_(idata__), fdata_(fdata__) { }
00338 
00339 
00340   // could declare member functions here
00341 
00342   // you should not declare data members here, all your data members should be serializable!
00343 
00344   // can access data members either directly as idata_ and fdata_ (which are private), or through the public member
00345   // functions idata() and fdata() which both exist in const and non-const versions
00346 };
00347 
00348 // we just need to implement toString() outside the class declaration:
00349 std::string MySimEvent2::toString() const
00350 { return SimEvent::toString() + "MySimEvent2 Message"; }
00351 
00352 // ######################################################################
00353 class DerSimEvent2 : public MySimEvent2 {
00354 
00355   // bare definition, only our vars, serialize and access functions, no constr, destr, or toString()
00356   SIMEVENT_CLASS_DEFINITION_BARE( DerSimEvent2, MySimEvent2,
00357                                   (( std::string, sdata ))
00358                                   (( std::vector<byte>, vdata )) )
00359 
00360 public:
00361   // could declare alternate (parameterized) constructors here, for example:
00362   DerSimEvent2(SimModule* src__, const int idata__, const float fdata__,
00363                const std::string& sdata__, const std::vector<byte>& vdata__) :
00364   MySimEvent2(src__, idata__, fdata__), sdata_(sdata__), vdata_(vdata__) { }
00365 
00366   // could declare member functions here
00367 
00368   // you should not declare data members here, all your data members should be serializable!
00369 
00370   // finally need to declare and implement constr, destr, and toString() function:
00371 
00372   // can both declare and implement here
00373   DerSimEvent2(SimModule* src = 0) : MySimEvent2(src) { /* do something cool */ }
00374 
00375   // can both declare and implement here
00376   virtual ~DerSimEvent2() { /* do something rad */ }
00377 
00378   // or can just declare and will implement later
00379   std::string toString() const;
00380 };
00381 
00382 // need to implement toString() outside the class declaration:
00383 std::string DerSimEvent2::toString() const
00384 { return MySimEvent2::toString() + "DerSimEvent2 Message"; }
00385 
00386 // ######################################################################
00387 // ######################################################################
00388 // Test program:
00389 // ######################################################################
00390 // ######################################################################
00391 
00392 // choose MySimEvent or MySimEvent2, DerSimEvent or DerSimEvent2
00393 #if 0
00394 #  define MYSIMEVENT MySimEvent
00395 #  define DERSIMEVENT DerSimEvent
00396 #else
00397 #  define MYSIMEVENT MySimEvent2
00398 #  define DERSIMEVENT DerSimEvent2
00399 #endif
00400 
00401 int main(int argc, const char **argv)
00402 {
00403   // create and open a character archive for output
00404   std::ofstream ofs("test-serialization.object");
00405 
00406   // create class instance
00407   SimModule *sm = 0;
00408   std::vector<byte> v; v.push_back(byte(3)); v.push_back(byte(42));
00409   std::string str("serialization inferno");
00410   const DERSIMEVENT s(sm, 5, 10.0F, str, v);
00411 
00412   LINFO("original data: %d %f '%s' [%d %d]", s.idata(), s.fdata(), s.sdata().c_str(), s.vdata()[0], s.vdata()[1]);
00413 
00414   // save data to archive
00415   {
00416     boost::archive::text_oarchive oa(ofs);
00417     // write class instance to archive
00418     oa << s;
00419     // archive and stream closed when destructors are called
00420   }
00421 
00422   // ... some time later restore the class instance to its orginal state
00423   DERSIMEVENT ss(sm);
00424 
00425   LINFO("new object before load: %d %f '%s' []", ss.idata(), ss.fdata(), ss.sdata().c_str());
00426 
00427   {
00428     // create and open an archive for input
00429     std::ifstream ifs("test-serialization.object");
00430     boost::archive::text_iarchive ia(ifs);
00431     // read class state from archive
00432     ia >> ss;
00433     // archive and stream closed when destructors are called
00434   }
00435 
00436   LINFO("re-loaded data: %d %f '%s' [%d %d]", s.idata(), s.fdata(), s.sdata().c_str(), s.vdata()[0], s.vdata()[1]);
00437 
00438   return 0;
00439 }
00440 
00441 
00442 #endif
00443 
00444 // ######################################################################
00445 /* So things look consistent in everyone's emacs... */
00446 /* Local Variables: */
00447 /* mode: c++ */
00448 /* indent-tabs-mode: nil */
00449 /* End: */
Generated on Sun May 8 08:42:18 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3