| 1 | // This may look like C code, but it is really -*- C++ -*-
 | 
|---|
| 2 | 
 | 
|---|
| 3 | #ifndef PPERSIST_H_SEEN
 | 
|---|
| 4 | #define PPERSIST_H_SEEN
 | 
|---|
| 5 | 
 | 
|---|
| 6 | // Flat file persistance, similar to Java serialization
 | 
|---|
| 7 | //
 | 
|---|
| 8 | // E. Aubourg     CEA DAPNIA/SPP  1999
 | 
|---|
| 9 | // R. Ansari      LAL IN2P3/CNRS  03/2000
 | 
|---|
| 10 | 
 | 
|---|
| 11 | // -------------------- Historique -----------------------
 | 
|---|
| 12 | //  Separe en deux (CVS version 1.19 - ppersist.h)  
 | 
|---|
| 13 | //  Classes PPFBinaryIn/OutputStream ds ppfbinstream.h
 | 
|---|
| 14 | // -------------------------------------------------------
 | 
|---|
| 15 | 
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #include "machdefs.h"
 | 
|---|
| 18 | #include "pexceptions.h"
 | 
|---|
| 19 | #include "gnumd5.h"
 | 
|---|
| 20 | #include "ppfbinstream.h"
 | 
|---|
| 21 | 
 | 
|---|
| 22 | #include <string>
 | 
|---|
| 23 | #include <map>
 | 
|---|
| 24 | #include <vector>
 | 
|---|
| 25 | #include <typeinfo>
 | 
|---|
| 26 | 
 | 
|---|
| 27 | 
 | 
|---|
| 28 | // Classe de base pour les objets qui peuvent devenir PPersist
 | 
|---|
| 29 | 
 | 
|---|
| 30 | namespace SOPHYA {
 | 
|---|
| 31 |   
 | 
|---|
| 32 |   class AnyDataObj;
 | 
|---|
| 33 | 
 | 
|---|
| 34 |   class PIOPersist;
 | 
|---|
| 35 |   class PInPersist;
 | 
|---|
| 36 |   class POutPersist;
 | 
|---|
| 37 |   class PPersist;
 | 
|---|
| 38 | 
 | 
|---|
| 39 | //! Persistent (delegate or mixin) base class 
 | 
|---|
| 40 |   class PPersist  {
 | 
|---|
| 41 |   public:
 | 
|---|
| 42 |     virtual           ~PPersist() {}
 | 
|---|
| 43 | 
 | 
|---|
| 44 |     void               Write(string const& fn) const;
 | 
|---|
| 45 |     void               Read(string const& fn);
 | 
|---|
| 46 | 
 | 
|---|
| 47 |     virtual void       Write(POutPersist&) const;
 | 
|---|
| 48 |     void               Read(PInPersist& s);               // Reads the type tag and the object
 | 
|---|
| 49 |     void               Write(POutPersist&, string const& tag) const; 
 | 
|---|
| 50 |     void               ReadAtTag(PInPersist& s, string const& tag);
 | 
|---|
| 51 | 
 | 
|---|
| 52 |     virtual AnyDataObj* DataObj()=0;       // Retourne l'objet reel 
 | 
|---|
| 53 |     virtual void       SetDataObj(AnyDataObj &)=0;     
 | 
|---|
| 54 | 
 | 
|---|
| 55 |     virtual uint_8     getMemOId() const ;      // Renvoie l'identificateur de l'objet  - par defaut=0
 | 
|---|
| 56 |     // Ces deux methodes doivent etre redefinies si   getMemOId() renvoie non nul (>0)
 | 
|---|
| 57 |     virtual void       ShareDataReference(PPersist &);       
 | 
|---|
| 58 |     virtual PPersist*  CloneSharedReference();
 | 
|---|
| 59 |                                                 // doit etre surcharge pour renvoyer un mem-oid correct
 | 
|---|
| 60 |   protected:  
 | 
|---|
| 61 |     virtual void       ReadSelf(PInPersist&)=0;           
 | 
|---|
| 62 |     virtual void       WriteSelf(POutPersist&) const=0;
 | 
|---|
| 63 | 
 | 
|---|
| 64 |     friend class       PInPersist;
 | 
|---|
| 65 |     friend class       POutPersist;
 | 
|---|
| 66 |   };
 | 
|---|
| 67 | 
 | 
|---|
| 68 | 
 | 
|---|
| 69 | 
 | 
|---|
| 70 | // Handles (statically) the registration of classes.
 | 
|---|
| 71 | 
 | 
|---|
| 72 |   class PIOPersist {
 | 
|---|
| 73 |   public:
 | 
|---|
| 74 |     typedef PPersist*            (*ClassCreatorFunc)();
 | 
|---|
| 75 |   
 | 
|---|
| 76 |     static void                  RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f);
 | 
|---|
| 77 |     static void                  RegisterDataObjClass(uint_8 classId, string class_name);
 | 
|---|
| 78 | 
 | 
|---|
| 79 |     static void                  ListPPHandlers();
 | 
|---|
| 80 |     static void                  ListDataObjClasses();
 | 
|---|
| 81 | 
 | 
|---|
| 82 |     static ClassCreatorFunc      FindCreatorFunc(uint_8 classId);
 | 
|---|
| 83 | 
 | 
|---|
| 84 |     static string                getPPClassName(uint_8 classId);
 | 
|---|
| 85 |     static uint_8                getPPClassId(string const & typ_name);
 | 
|---|
| 86 |     static uint_8                getPPClassId(PPersist const & ppo);
 | 
|---|
| 87 |     static string                getDataObjClassName(uint_8 classId);
 | 
|---|
| 88 |     static uint_8                getDataObjClassId(string const & typ_name);
 | 
|---|
| 89 |     static uint_8                getDataObjClassId(AnyDataObj const & o);
 | 
|---|
| 90 | 
 | 
|---|
| 91 |     static uint_8 Hash(string const& typname);
 | 
|---|
| 92 |     static MD5_CONTEXT ctx;
 | 
|---|
| 93 |   
 | 
|---|
| 94 |     static void Initialize();   // Pour initialiser classList
 | 
|---|
| 95 | 
 | 
|---|
| 96 | 
 | 
|---|
| 97 |   private:
 | 
|---|
| 98 | 
 | 
|---|
| 99 |     typedef map<uint_8, ClassCreatorFunc, less<uint_8> > ClassList;  
 | 
|---|
| 100 |     // Pas de createur appele pour objets statiques sur Linux - $CHECK$ Reza 26/04/99
 | 
|---|
| 101 |     static ClassList *           ppclassList;      // PPersist class list  
 | 
|---|
| 102 |     static map<string, uint_8> * ppclassNameList;  // PPersist classId = f(PPersistClassName)
 | 
|---|
| 103 |     static map<string, uint_8> * dobjclassNameList;  // PPersist classId = f(DataObjClassName)
 | 
|---|
| 104 | 
 | 
|---|
| 105 |   };
 | 
|---|
| 106 | 
 | 
|---|
| 107 | 
 | 
|---|
| 108 | // TBD : use hash tables instead of maps. Check hashtbl status in STL.
 | 
|---|
| 109 | 
 | 
|---|
| 110 | //! Input stream for PPersit objects.
 | 
|---|
| 111 |   class PInPersist : public PPFBinaryInputStream, public PIOPersist  {
 | 
|---|
| 112 |   public:
 | 
|---|
| 113 |     PInPersist(RawInOutStream * is, bool ad, bool scan=false);
 | 
|---|
| 114 |     PInPersist(string const& flnm, bool scan=true);
 | 
|---|
| 115 |     virtual ~PInPersist();
 | 
|---|
| 116 | 
 | 
|---|
| 117 |     // A faire - Reza Dec 2003
 | 
|---|
| 118 |     string     GetTagClassName(int itag);
 | 
|---|
| 119 |     //   Object Reading 
 | 
|---|
| 120 |     PPersist*  ReadObject();
 | 
|---|
| 121 |     void       GetObject(AnyDataObj & o);
 | 
|---|
| 122 |     void       GetObject(AnyDataObj & o, string  tagname);
 | 
|---|
| 123 |     PPersist*  GetPPObject(AnyDataObj * po=NULL);
 | 
|---|
| 124 | 
 | 
|---|
| 125 |     //  Reza 03/2000
 | 
|---|
| 126 |     //  Methodes qui pourraient etre protected, mais doivent etre utilisables par PPersist 
 | 
|---|
| 127 |     void   ReadReference(PPersist & ppo);  // Fill the ppo object from the reference tag
 | 
|---|
| 128 |     PPersist * ReadReference();            // Creates object from the reference tag
 | 
|---|
| 129 |     void   KeepOId(uint_8 oid, PPersist & ppo);        // Keeps the ppo in the objList
 | 
|---|
| 130 | 
 | 
|---|
| 131 |   protected:
 | 
|---|
| 132 | 
 | 
|---|
| 133 |     // already read objects 
 | 
|---|
| 134 |     typedef map<uint_8, PPersist * > ObjList;
 | 
|---|
| 135 |     ObjList objList;
 | 
|---|
| 136 |     friend class PPersist;
 | 
|---|
| 137 |   };
 | 
|---|
| 138 | 
 | 
|---|
| 139 | //! Output stream for PPersit objects.
 | 
|---|
| 140 |   class POutPersist : public PPFBinaryOutputStream, public PIOPersist  {
 | 
|---|
| 141 |   public:
 | 
|---|
| 142 |     POutPersist(RawInOutStream* os, bool ad, int endianness = PPS_NATIVE);
 | 
|---|
| 143 |     POutPersist(string const& flnm, int endianness = PPS_NATIVE);
 | 
|---|
| 144 |     virtual ~POutPersist();
 | 
|---|
| 145 | 
 | 
|---|
| 146 |     //    void   Put(PPersist const* x) {PutPPObject(x);}
 | 
|---|
| 147 | 
 | 
|---|
| 148 |     // Objet Write - Ecriture des objets
 | 
|---|
| 149 |     void PutPPObject (PPersist const*); // Like doing Write(stream) on PPersist object
 | 
|---|
| 150 | 
 | 
|---|
| 151 |     void PutObject(AnyDataObj & o);   // Creates the corresponding PPersist Object and call Write()
 | 
|---|
| 152 |     void PutObject(AnyDataObj & o, string tagname);
 | 
|---|
| 153 | 
 | 
|---|
| 154 | 
 | 
|---|
| 155 |   protected:
 | 
|---|
| 156 |     bool     serializeNullAndRepeat(PPersist const* x);
 | 
|---|
| 157 |     uint_8   findObjectId(PPersist const* x, int_8 & pos);
 | 
|---|
| 158 |     uint_8   assignObjectId(PPersist const* x);
 | 
|---|
| 159 | 
 | 
|---|
| 160 |     // objreftag contains the assigned POutStream Object Id and the stream position 
 | 
|---|
| 161 |     // of the original written object
 | 
|---|
| 162 |     typedef struct { uint_8 ppsoid; int_8 ppspos; } objreftag;
 | 
|---|
| 163 |     // already serialized objects are kept in a map as a function of the Objects memory Id
 | 
|---|
| 164 |     typedef map<uint_8, objreftag, less<uint_8> >  ObjList;
 | 
|---|
| 165 |     ObjList objList;
 | 
|---|
| 166 |     uint_8 pps_OId;    // PPS Object Id 
 | 
|---|
| 167 |     int    wobj_level; // Niveau d'imbrication lors de l'ecriture d'objet
 | 
|---|
| 168 |   };
 | 
|---|
| 169 |   
 | 
|---|
| 170 | //! \cond
 | 
|---|
| 171 | // Le macro suivant permettent de simplifier la declaration 
 | 
|---|
| 172 | // des operateurs >> << sur les POutPersist et  PInPersist
 | 
|---|
| 173 | #define RAWPERSISTIO(_Type_,_xtyp_)                                             \
 | 
|---|
| 174 |   inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
 | 
|---|
| 175 |   {                                                                               \
 | 
|---|
| 176 |     c.Put##_xtyp_(data);                                                          \
 | 
|---|
| 177 |     return c;                                                                     \
 | 
|---|
| 178 |   }                                                                               \
 | 
|---|
| 179 |                                                                                 \
 | 
|---|
| 180 |   inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
 | 
|---|
| 181 |   {                                                                               \
 | 
|---|
| 182 |     c.Get##_xtyp_(data);                                                          \
 | 
|---|
| 183 |     return c;                                                                     \
 | 
|---|
| 184 |   }                                                                               
 | 
|---|
| 185 | 
 | 
|---|
| 186 | // On utilise le macro RAWPERSISTIO pour declarer POutPersist << et PInPersist >> 
 | 
|---|
| 187 | // pour les types de base r_4 r_8 int_4 int_8 ...
 | 
|---|
| 188 |   RAWPERSISTIO(int_8,I8);
 | 
|---|
| 189 |   RAWPERSISTIO(uint_8,U8);
 | 
|---|
| 190 |   RAWPERSISTIO(int_4,I4);
 | 
|---|
| 191 |   RAWPERSISTIO(uint_4,U4);
 | 
|---|
| 192 |   RAWPERSISTIO(int_2,I2);
 | 
|---|
| 193 |   RAWPERSISTIO(uint_2,U2);
 | 
|---|
| 194 |   RAWPERSISTIO(char,Byte);
 | 
|---|
| 195 |   RAWPERSISTIO(r_4,R4);
 | 
|---|
| 196 |   RAWPERSISTIO(r_8,R8);
 | 
|---|
| 197 |   RAWPERSISTIO(complex<r_4>,Z4);
 | 
|---|
| 198 |   RAWPERSISTIO(complex<r_8>,Z8);
 | 
|---|
| 199 |   RAWPERSISTIO(string,Str);
 | 
|---|
| 200 |   
 | 
|---|
| 201 | #if 0
 | 
|---|
| 202 | #define STRUCTPERSISTIO(_Type_, _field_, _size_)                                \
 | 
|---|
| 203 |   inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
 | 
|---|
| 204 |   {                                                                               \
 | 
|---|
| 205 |     c.PutBytes(&data._field_, _size_);                                            \
 | 
|---|
| 206 |     return c;                                                                     \
 | 
|---|
| 207 |   }                                                                               \
 | 
|---|
| 208 |                                                                                 \
 | 
|---|
| 209 |   inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
 | 
|---|
| 210 |   {                                                                               \
 | 
|---|
| 211 |     c.GetBytes(&data._field_, _size_);                                            \
 | 
|---|
| 212 |     return c;                                                                     \
 | 
|---|
| 213 |   }                                                                               
 | 
|---|
| 214 | 
 | 
|---|
| 215 | #endif
 | 
|---|
| 216 | 
 | 
|---|
| 217 | //! \endcond  
 | 
|---|
| 218 | 
 | 
|---|
| 219 | // --- Cela risque d'etre dangereux --- On le laisse au niveau des DataObj
 | 
|---|
| 220 | //                           Reza 24/3/2000 
 | 
|---|
| 221 | //   inline POutPersist& operator << (POutPersist& c, PPersist const& obj)
 | 
|---|
| 222 | //     {
 | 
|---|
| 223 | //       obj.Write(c);
 | 
|---|
| 224 | //       return c;
 | 
|---|
| 225 | //     }
 | 
|---|
| 226 |   
 | 
|---|
| 227 | //   inline PInPersist& operator >> (PInPersist& c, PPersist& obj)
 | 
|---|
| 228 | //     {
 | 
|---|
| 229 | //       obj.Read(c);
 | 
|---|
| 230 | //       return c;
 | 
|---|
| 231 | //     }
 | 
|---|
| 232 | 
 | 
|---|
| 233 |   // Utility class to
 | 
|---|
| 234 |   //   - compute the class ID from a MD5 hash of the class name
 | 
|---|
| 235 |   //   - register classes with PIOPersist, through PPRegister macro
 | 
|---|
| 236 | 
 | 
|---|
| 237 | //! template class for handling the PPersist registration mechanism.
 | 
|---|
| 238 |   template <class T>
 | 
|---|
| 239 |     class PPersistRegistrar {
 | 
|---|
| 240 |     public:
 | 
|---|
| 241 |       static PPersist* Create() {return new T();}
 | 
|---|
| 242 |       static void Register(string id) { PIOPersist::RegisterPPHandlerClass(Hash(id), typeid(T).name(), Create); }
 | 
|---|
| 243 |       static uint_8 Hash(string id) {
 | 
|---|
| 244 |         return PIOPersist::Hash(id);
 | 
|---|
| 245 |       }
 | 
|---|
| 246 |     };
 | 
|---|
| 247 |   
 | 
|---|
| 248 | #define PPRegister(className) PPersistRegistrar< className >::Register( #className );
 | 
|---|
| 249 | #define DObjRegister(ppclassName, className) PIOPersist::RegisterDataObjClass(PIOPersist::Hash(#ppclassName), typeid(className).name());
 | 
|---|
| 250 | 
 | 
|---|
| 251 | } // namespace SOPHYA
 | 
|---|
| 252 | 
 | 
|---|
| 253 | // La classe PPFNameTag facilite la manipulation des Nametag ds les fichiers
 | 
|---|
| 254 | // PPersist - definie ds ppfnametag.h
 | 
|---|
| 255 | #include "ppfnametag.h"
 | 
|---|
| 256 | 
 | 
|---|
| 257 | 
 | 
|---|
| 258 | #endif
 | 
|---|