Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Serializer

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Serializer 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.11 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_SERIALIZER_
00026 #define _BASE_SERIALIZER_
00027 
00028 #include <base/base>
00029 #include <base/Serializable>
00030 #include <base/Referenced>
00031 #include <base/array>
00032 #include <base/ref>
00033 #include <base/reflist>
00034 #include <base/serialization_error>
00035 #include <base/VFile>
00036 
00037 #include <base/Time>
00038 #include <base/Vector3>
00039 #include <base/Quat4>
00040 #include <base/Orient>
00041 #include <base/Matrix3>
00042 #include <base/Matrix4>
00043 #include <base/Vector>
00044 #include <base/Matrix>
00045 
00046 
00047 #include <iostream>
00048 #include <list>
00049 
00050 
00051 namespace base {
00052 
00053 class Serializable;
00054 
00055 
00056 class Serializer : public Object
00057 {
00058 public:
00059   enum SerializerType { Input=0, Output=1 };
00060   Serializer(SerializerType type);
00061   Serializer(SerializerType type, ref<VFile> archive); 
00062   Serializer(SerializerType type, std::ios& stream);
00063   virtual ~Serializer();
00064 
00065   virtual bool isOutput() const { return output; }     ///< true is this is an output serialization stream
00066   virtual bool isInput() const { return !isOutput(); } ///< true if this is an input serialization stream
00067 
00068   /** If follow is true (default) serialized references will cause the object being referenced to 
00069       be serialized (if it hasn't been already).  For complex data structures this recursive serialization
00070       of objects (and hence object they reference in turn), may cause excessive stack usage.
00071       If follow is false then the objects to which references refer will NOT be serialized.  It is then
00072       up to the client to ensure that all referenced objects are ultimately serialized in the stream.
00073       Upon destruction, the Serializer *may* throw an exception if there are outstanding references
00074       to objects that have not been serialized.
00075       Returns the previous value (which most serialize() methods should restore before returning)
00076   */
00077   virtual bool followReferences(bool follow);
00078 
00079 
00080   /** The operator() method is overloaded for all types that can be serialized
00081       (including classes that derive from Serializable, in which case their
00082        serialize() method is called with *this Serializer).
00083       For example: (assuming class B is-a Serialiable)
00084       class A : public Serializable
00085       {
00086       public:
00087         int  a;
00088         Real b
00089         ref<B> c;
00090         B d;
00091         std::list<B> e;
00092 
00093         void serialize(Serializer& s) { s(a)(b)(c)(d)(e); }
00094       }
00095       
00096       The serialize() method will input or output (depending in the type of
00097        the Serializer s) the values a & b, will call c->serialize(s) if necessary
00098        (for example, on Output, if the object *c hasn't already been serialized),
00099        will call d.serialize() and also B::serialize(s) for each element of e.
00100 
00101       NB: all serialization operator() methods have undefined behavior
00102       for input streams that are exhausted, except char & Byte, which return std::EOF
00103    */
00104 
00105   
00106   /// emit comments into the serialization stream.  Does nothing if not an output stream or the format doesn't support comments
00107   Serializer& comment(const String& comment) { serializeComment(comment); return *this; }
00108 
00109   enum Hint { Indent=0, Unindent=1 };
00110   /// provide a hint.  The meaning is specific particular serializers and may be ignored/have no effect
00111   virtual Serializer& hint(Int h) { return *this; }
00112 
00113 
00114   // Serialization of simple types 
00115   Serializer& operator()(char& c, const String& memberName = "")       { return serialize(c, memberName); }
00116   Serializer& operator()(const char& c, const String& memberName = "") 
00117   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<char&>(c), memberName); }
00118 
00119   Serializer& operator()(Byte& b, const String& memberName = "")       { return serialize(b, memberName); }
00120   Serializer& operator()(const Byte& b, const String& memberName = "") 
00121   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<Byte&>(b), memberName); }
00122 
00123   Serializer& operator()(bool& b, const String& memberName = "")       { return serialize(b, memberName); }
00124   Serializer& operator()(const bool& b, const String& memberName = "") 
00125   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<bool&>(b), memberName); }
00126 
00127   Serializer& operator()(SInt& i, const String& memberName = "")       { return serialize(i, memberName); }
00128   Serializer& operator()(const SInt& i, const String& memberName = "") 
00129   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<SInt&>(i), memberName); }
00130 
00131   Serializer& operator()(Int& i, const String& memberName = "")        { return serialize(i, memberName); }
00132   Serializer& operator()(const Int& i, const String& memberName = "")  
00133   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<Int&>(i), memberName); }
00134 
00135   Serializer& operator()(LInt& i, const String& memberName = "")       { return serialize(i, memberName); }
00136   Serializer& operator()(const LInt& i, const String& memberName = "") 
00137   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<LInt&>(i), memberName); }
00138 
00139   Serializer& operator()(Real& r, const String& memberName = "")       { return serialize(r, memberName); }
00140   Serializer& operator()(const Real& r, const String& memberName = "") 
00141   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<Real&>(r), memberName); }
00142 
00143 
00144   // Serialization of light weight (non-Serializable) composite types 
00145   Serializer& operator()(String& s, const String& memberName = "")     { return serialize(s, memberName); }
00146   Serializer& operator()(const String& s, const String& memberName = "") 
00147   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<String&>(s), memberName); }
00148 
00149   Serializer& operator()(Time& t, const String& memberName = "")
00150   { t.serialize(*this); return *this; }
00151   Serializer& operator()(const Time& t, const String& memberName = "") 
00152   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Time&>(t), memberName); }
00153 
00154   Serializer& operator()(Vector3& v, const String& memberName = "")
00155   { v.serialize(*this); return *this; }
00156   Serializer& operator()(const Vector3& v, const String& memberName = "") 
00157   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Vector3&>(v), memberName); }
00158 
00159   Serializer& operator()(Quat4& q, const String& memberName = "")
00160   { q.serialize(*this); return *this; }
00161   Serializer& operator()(const Quat4& q, const String& memberName = "") 
00162   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Quat4&>(q), memberName); }
00163 
00164   Serializer& operator()(Orient& o, const String& memberName = "")
00165   { o.serialize(*this); return *this; }
00166   Serializer& operator()(const Orient& o, const String& memberName = "") 
00167   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Orient&>(o), memberName); }
00168 
00169   Serializer& operator()(Matrix3& m, const String& memberName = "")
00170   { m.serialize(*this); return *this; }
00171   Serializer& operator()(const Matrix3& m, const String& memberName = "") 
00172   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Matrix3&>(m), memberName); }
00173 
00174   Serializer& operator()(Matrix4& m, const String& memberName = "")
00175   { m.serialize(*this); return *this; }
00176   Serializer& operator()(const Matrix4& m, const String& memberName = "") 
00177   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Matrix4&>(m), memberName); }
00178 
00179   Serializer& operator()(Vector& v, const String& memberName = "");
00180   Serializer& operator()(const Vector& v, const String& memberName = "") 
00181   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Vector&>(v), memberName); }
00182 
00183   Serializer& operator()(Matrix& m, const String& memberName = "");
00184   Serializer& operator()(const Matrix& m, const String& memberName = "") 
00185   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return operator()(const_cast<Matrix&>(m), memberName); }
00186     
00187 
00188 
00189   // serialization of references complex types (derived from Serializable),
00190   //  references (ref<T>, T derived from Serializable), and supported containers
00191   //  (e.g. array)
00192 
00193   Serializer& operator()(Serializable& r, const String& memberName = "") { return serialize(r, memberName); }
00194   Serializer& operator()(const Serializable& r, const String& memberName = "") 
00195   { if (!output) throw serialization_error(Exception(inputToConstErrorString)); else return serialize(const_cast<Serializable&>(r), memberName); }
00196 
00197 
00198   // ref<T>
00199   template<class T>
00200   Serializer& operator()(ref<T>& r, const String& memberName = "")
00201   {
00202     T* p = GetImplRef(r);
00203     
00204     Serializable* sp = 0;
00205     if (p!=0) {
00206       if (!instanceof(*p,Serializable))
00207         throw serialization_error(Exception("can only archive references to Serializable derived classes (ref<Serializable>)"));
00208       sp = dynamic_cast<Serializable*>(p);
00209     }
00210 
00211     if (!output) {
00212       Serializable::SerializableDerivedInstantiator<T> i;
00213       serializePointer(sp,(sp==0)?&i:0, memberName);
00214       Assert(sp);
00215       p = dynamic_cast<T*>(sp);
00216       Reset(r,p);  
00217     }
00218     else
00219       serializePointer(sp,0, memberName);
00220 
00221     return *this;
00222   }
00223 
00224   // ref<T> where T is a (possible abstract) base of the subclass being serialized
00225   template<class T>
00226   Serializer& baseRef(ref<T>& r, const String& memberName = "")
00227   {
00228     T* p = GetImplRef(r);
00229     
00230     Serializable* sp = 0;
00231     if (p!=0) {
00232       if (!instanceof(*p,Serializable))
00233         throw serialization_error(Exception("can only archive references to Serializable derived classes (ref<Serializable>)"));
00234       sp = dynamic_cast<Serializable*>(p);
00235     }
00236 
00237     if (!output) {
00238       // can't utilize an existing instance it may not be the correct subclass
00239       r = ref<T>();
00240       sp = 0; 
00241       serializePointer(sp,0, memberName,true);
00242       Assert(sp);
00243       p = dynamic_cast<T*>(sp);
00244       Reset(r,p);  
00245     }
00246     else
00247       serializePointer(sp,0, memberName, true);
00248 
00249     return *this;
00250   }
00251 
00252 
00253   template<class T>
00254   Serializer& operator()(const ref<T>& r, const String& memberName = "")
00255   {
00256     if (!output)
00257       throw serialization_error(Exception("can't input to a const ref<>"));
00258 
00259     T* p = GetImplRef(r);
00260 
00261     Serializable* sp = 0;
00262     if (p != 0) {
00263       if (!instanceof(*p,Serializable))
00264         throw serialization_error(Exception("can only archive references to Serializable derived classes (ref<Serializable>)"));
00265       sp = dynamic_cast<Serializable*>(p);
00266     }
00267     serializePointer(sp,0, memberName);
00268     return *this;
00269   }
00270 
00271 
00272   // array
00273   template<class T>
00274   Serializer& operator()(array<T>& a, const String& memberName = "")
00275   {
00276     serializeComment(String("begin array ")+memberName);
00277     Int size = a.size();
00278     operator()(size, "size");
00279     for(Int i=0; i<size; i++)
00280       operator()(a.at(i));
00281     serializeComment(String("end array ")+memberName);
00282     return *this;
00283   }
00284 
00285   template<class T>
00286   Serializer& operator()(const array<T>& a, const String& memberName = "")
00287   {
00288     if (!output)
00289       throw serialization_error(Exception(inputToConstErrorString));
00290 
00291     serializeComment(String("begin array ")+memberName);
00292     Int size = a.size();
00293     operator()(size, "size");
00294     for(Int i=0; i<a.size(); i++)
00295       operator()(a[i]);
00296     serializeComment(String("end array ")+memberName);
00297     return *this;
00298   }
00299 
00300   // std::list<T>
00301   template<class T>
00302   Serializer& operator()(std::list<T>& l, const String& memberName = "")
00303   {
00304     if (output) {
00305       serializeComment(String("begin list ")+memberName);
00306       Int size = l.size();
00307       operator()(size, "size");
00308       typename std::list<T>::iterator i = l.begin();
00309       typename std::list<T>::iterator end = l.end();
00310       while (i != end) {
00311         operator()(*i);
00312         ++i;
00313       }
00314       serializeComment(String("end list ")+memberName);
00315     }
00316     else {
00317       l.clear();
00318       Int size;
00319       operator()(size, "size");
00320       if (size > 0) {
00321         T e;
00322         for(Int i=0; i<size; i++) {
00323           operator()(e);
00324           l.push_back( e );
00325         }
00326       }
00327     }
00328 
00329     return *this;
00330   }
00331 
00332   template<class T>
00333   Serializer& operator()(const std::list<T>& a, const String& memberName = "")
00334   {
00335     if (!output)
00336       throw serialization_error(Exception(inputToConstErrorString));
00337     return operator()(const_cast<std::list<T>&>(a), memberName);
00338   }
00339 
00340 
00341   // reflist<T>
00342   template<class T>
00343   Serializer& operator()(reflist<T>& l, const String& memberName = "")
00344   {
00345     if (output) {
00346       serializeComment(String("begin reflist ")+memberName);
00347       Int size = l.size();
00348       operator()(size, "size");
00349       typename reflist<T>::iterator i = l.begin();
00350       typename reflist<T>::iterator end = l.end();
00351       while (i != end) {
00352         operator()(*i);
00353         ++i;
00354       }
00355       serializeComment(String("end reflist ")+memberName);
00356     }
00357     else {
00358       l.clear();
00359       Int size;
00360       operator()(size, "size");
00361       if (size > 0) {
00362         for(Int i=0; i<size; i++) {
00363           ref<T> e(0);
00364           operator()(e);
00365           l.push_back( e );
00366         }
00367       }
00368     }
00369 
00370     return *this;
00371   }
00372 
00373   template<class T>
00374   Serializer& operator()(const reflist<T>& l, const String& memberName = "")
00375   {
00376     if (!output)
00377       throw serialization_error(Exception(inputToConstErrorString));
00378     return operator()(const_cast<reflist<T>&>(l), memberName);
00379   }
00380 
00381 
00382   virtual void flush() = 0;
00383 
00384 protected:  
00385   Serializer(const Serializer& s) : output(s.output), follow(s.follow), aborted(s.aborted) {}
00386 
00387   const static String inputToConstErrorString;
00388 
00389   // helpers
00390   virtual void serializeReferenceIndex(Int& index)
00391     { operator()(index,"refindex"); }
00392   virtual void serializePointer(Serializable*& p, Serializable::SerializableInstantiator* i, const String& memberName, bool forceTypeSerialization = false);
00393 
00394   void abort(const String& exceptionString); // flags the serialization as aborted and throws an exception
00395 
00396 
00397   // specialized Serializers need only implement these
00398   //  (for convenience only the non-const parameter versions are
00399   //   required.  This means that for Output type serializers,
00400   //   these functions should *not* modify the parameter.  The
00401   //   parameter has had its constness cast away before being passed)
00402   virtual Serializer& serialize(char& c, const String& memberName) = 0;
00403   virtual Serializer& serialize(Byte& b, const String& memberName) = 0;
00404   virtual Serializer& serialize(bool& b, const String& memberName) = 0;
00405   virtual Serializer& serialize(SInt& i, const String& memberName) = 0;
00406   virtual Serializer& serialize(Int& i, const String& memberName) = 0;
00407   virtual Serializer& serialize(LInt& i, const String& memberName) = 0;
00408   virtual Serializer& serialize(String& s, const String& memberName) = 0;
00409   virtual Serializer& serialize(Real& r, const String& memberName) = 0;
00410 
00411 
00412   enum TypeModifier { UnknownType          = 0,
00413                       ObjectType           = 1,
00414                       ReferencedObjectType = 2,
00415                       ObjectReferenceType  = 3,
00416                       InvalidType          = 4 };
00417   ///  serializes object or reference header
00418   /**
00419    *   Typically serializes the object or reference type (at minimum a flag indicating if a referenced object is present in the
00420    *   stream, or just an object reference).  Called just before an object or reference is serialized (by serialize(Serializable&) 
00421    *   or serializePointer() ).
00422    *    
00423    *   @param      typeName      Object type name as returned from typeid().name(). 
00424    *                             For output, the type of the object is passed.  In the case of referenced objects
00425    *                             it shound't be the pointer or reference type, just the referenced object type.
00426    *                             For input streams, the expected type is passed, or the empty string if the object type
00427    *                             to be read is unknown (if, for example, the serialization format doesn't include type information)
00428    *                             If the serialization format does contain the object type information, it is returned, otherwise
00429    *                             the parameter is unaltered.
00430    *
00431    *   @param      typeModifier  Modifies typeName to indicate unreferencable objects, referenced objects and object references.
00432    *                             For output, the value ObjectType is passed for single instance objects.  For referenced objects,
00433    *                             ReferencedObjectType is passed if the object itself will subsequently be serialized,
00434    *                             or ObjectReferenceType if subsequently only a reference to the object (elsewhere in
00435    *                             the stream) will be serialized.
00436    *                             For input, the values passed are as for output, except that if it is unknown if
00437    *                             a referenced object or just a reference will subsequently be read, UnknownType is passed,
00438    *                             and either the value ReferencedObjectType or ObjectReferenceType will be returned.
00439    *
00440    *   @param      memberName    An optional name for the reference being serialized.  This must be the same on input
00441    *                             as was supplied on output.
00442    *
00443    *   @param      forceTypeSerialization Usually the type of object being input can be deduced from the type of
00444    *                                      the reference.  However, when serializing derived classes via a reference
00445    *                                      to a base class, it is not possible to determine which derived class to
00446    *                                      instantiate on input unless the type is stored in the serialization stream.
00447    *                                      For Serializers that don't usually store the referenced object type on output,
00448    *                                      this parameter is used to force them to do so.
00449    *
00450    *   @return     For output, the parameter typeModifier is returned.  For input, one of ObjectType, ReferencedObjectType or ObjectReferenceType is returned.
00451    *   @exception  serialization_error if unexpected input is found.
00452    *
00453    * Note that as the strings returned by typeid().name() are not portable accross compilers, they shouldn't be
00454    *      embedded into serialization streams.  Use base::className(typeid()) to obtain a portable type string.
00455    */
00456   virtual TypeModifier preSerializeObject(String& typeName, TypeModifier typeModifier, const String& memberName, bool forceTypeSerialization = false) = 0;
00457 
00458   /// serialize an object or reference 'footer'
00459   /** Called just after an object or reference has been serialized (by serialize(Serializable&) or serializePointer() ). */
00460   virtual void         postSerializeObject(const String& memberName) = 0;
00461 
00462 
00463   /// only override this to re-implement 
00464   virtual Serializer& serialize(Serializable& r, const String& memberName);
00465 
00466   /// override this if the serialization format supports comments
00467   virtual void serializeComment(const String& comment) {}
00468 
00469 
00470 
00471 
00472   bool output;
00473   bool follow;
00474   bool aborted;
00475 
00476   Int ptrIndex(Serializable* p);
00477 
00478   array<Serializable*> ptrs;
00479   array<bool>          serialized;
00480   Int serializePointerRecursionDepth;
00481   Int depthAtFollowDisable; // serializePointerRecursionDepth value when follow was last set false (follow pointer's only one level below)
00482 };
00483 
00484 
00485 } // base
00486 
00487 #endif

Generated on Thu Jul 29 15:56:13 2004 for OpenSim by doxygen 1.3.6