Index: trunk/SophyaLib/BaseTools/ppersist.h
===================================================================
--- trunk/SophyaLib/BaseTools/ppersist.h	(revision 219)
+++ trunk/SophyaLib/BaseTools/ppersist.h	(revision 241)
@@ -1,16 +1,20 @@
+// This may look like C code, but it is really -*- C++ -*-
+
 #ifndef PPERSIST_H_SEEN
 #define PPERSIST_H_SEEN
 
-// Classe mixin pour implementer une persistance pas trop bete.
-
-#include "defs.h"
-#include "machine.h"
-#include "perrors.h"
-#include "pclassids.h"
+// Flat file persistance, similar to Java serialization
+//
+// E. Aubourg     CEA DAPNIA/SPP  1999
+
+
+#include "machdefs.h"
+#include "pexceptions.h"
+#include "md5.h"
 
 #include <string>
-#include <list>
 #include <map>
-#include <functional>
+#include <vector>
+#include <typeinfo>
 
 #if defined(__KCC__)
@@ -21,306 +25,295 @@
 #endif
 
-#ifdef RFIO
-#include "erostream.h"
-#else
-#include <iostream.h>
-#endif
-
-
-class PPersistMgr;
-class PPersist;
-class PShPersist;
-class PInPersist;
-class POutPersist;
-
-typedef less<int_4> Int4Compare;
-
-class PPersistMgr {
-public:
-  typedef PPersist*           (*ClassCreatorFunc)();
-  
-  static void                  RegisterClass(int_4 classId, ClassCreatorFunc f,
-                                             bool shared=false);
-  static PPersist*             ReadObject(PInPersist&);
-  
-  static ClassCreatorFunc      FindCreatorFunc(int_4 classId);
-  static ClassCreatorFunc      FindCreatorFunc(int_4 classId, bool& isShared);
-  
-  static void                  Reset();  // Nouveau fichier, on oublie les objets partages.
-
-#ifndef __DECCXX
-private:
-#endif
-  struct  ClassListEntry {
-    bool             shared;
-    ClassCreatorFunc f;
+namespace PlanckDPC {
+  
+  class PIOPersist;
+  class PInPersist;
+  class POutPersist;
+  class PPersist;
+
+  /* Persistant (delegate or mixin) object */
+
+  class PPersist  {
+  public:
+    virtual           ~PPersist() {}
+
+    void               Write(string const& fn) const;
+    void               Read(string const& fn);
+
+    virtual void       Write(POutPersist&) const;
+    void               Read(PInPersist& s);               // Reads the type tag and the object
+    void               Write(POutPersist&, string const& tag) const; 
+    void               ReadAtTag(PInPersist& s, string const& tag);
+  protected:  
+    virtual void       ReadSelf(PInPersist&)=0;           
+    virtual void       WriteSelf(POutPersist&) const=0;  
+
+    friend class       PInPersist;
+    friend class       POutPersist;
   };
-#ifdef __DECCXX
-private:
-#endif
-
-  typedef map<int_4, ClassListEntry, Int4Compare> ClassList;
-
-
-  static ClassList*            classList;
-  friend class                 PeidaInitiator;
-};
-
-
-
-class PPersist EXC_AWARE {
-public:
-  enum {PPS_NATIVE = -1, PPS_LITTLE_ENDIAN = 0, PPS_BIG_ENDIAN = 1};
-  virtual                   ~PPersist() {}
-  virtual int_4              ClassId() const=0;
-
-          void               Write(string const& fn) const;
-          void               Read(string const& fn);
-
-  virtual void               Write(POutPersist&) const;
-          void               Read(PInPersist& s);  // Se lit, y compris le tag de type.
-          int_4              Write(POutPersist&, int_4 key) const; 
-          int_4              Write(POutPersist&, int_4 key, string& nom) const; 
-          void               ReadAtTag(PInPersist& s, int_4 tagid);
-          void               ReadAtKey(PInPersist& s, int_4 key);
-protected:  
-  virtual void               ReadSelf(PInPersist&)=0;        // A redefinir...
-  virtual void               WriteSelf(POutPersist&) const=0; // A redefinir...
-
-  friend class               PPersistMgr;
-};
-
-class PShPersist : public PPersist{
-public:
-                             PShPersist() :mObjectID(0) {}
-  virtual                   ~PShPersist();
-  virtual void               Write(POutPersist&) const;
-  static PShPersist*         FindObject(int_4 objId);
-  
-private:
-  typedef map<int_4, PShPersist*, Int4Compare> ObjList;
-
-  static ObjList*            objList;
-  /*mutable*/ int_4          mObjectID;
-  friend class               PPersistMgr;
-  friend class               PeidaInitiator;
-};
-
-
-
-class PInPersist {
-public:
-  PInPersist(string const& flnm, bool scan=true);
-  ~PInPersist();
-
-  bool   GotoTag(int_4 num);
-  bool   GotoKey(int_4 key, int rang=0);
-  int    NbKey(int_4 key);
-  void   ListTags();
-  inline int_4   NbTags() { return(mNTags); } 
-  int_4  TagKey(int_4 num, int_4& cid, int_4& ln);
-  string TagName(int_4 num);
-
-  void   GetByte (char& c);
-  void   GetBytes(void* ptr, size_t bytes);
-  void   GetR4   (r_4&);
-  void   GetR4s  (r_4*, size_t);
-  void   GetR8   (r_8&);
-  void   GetR8s  (r_8*, size_t);
-  void   GetI2   (int_2&);
-  void   GetI2s  (int_2*, size_t);
-  void   GetU2   (uint_2&);
-  void   GetU2s  (uint_2*, size_t);
-  void   GetI4   (int_4&);
-  void   GetI4s  (int_4*, size_t);
-  void   GetU4   (uint_4&);
-  void   GetU4s  (uint_4*, size_t);
-  void   GetI8   (int_8&);
-  void   GetI8s  (int_8*, size_t);
-  void   GetU8   (uint_8&);
-  void   GetU8s  (uint_8*, size_t);
-  void   GetLine (char* ptr, size_t len);
-
-  void   Get(char&   c) {GetByte(c);}
-  void   Get(r_4&    x) {GetR4(x);}
-  void   Get(r_8&    x) {GetR8(x);}
-  void   Get(uint_2& x) {GetU2(x);}
-  void   Get(int_2&  x) {GetI2(x);}
-  void   Get(uint_4& x) {GetU4(x);}
-  void   Get(int_4&  x) {GetI4(x);}
-  void   Get(uint_8& x) {GetU8(x);}
-  void   Get(int_8&  x) {GetI8(x);}
-  void   Get(r_4*    x, size_t n) {GetR4s(x,n);}
-  void   Get(r_8*    x, size_t n) {GetR8s(x,n);}
-  void   Get(uint_2* x, size_t n) {GetU2s(x,n);}
-  void   Get(int_2*  x, size_t n) {GetI2s(x,n);}
-  void   Get(uint_4* x, size_t n) {GetU4s(x,n);}
-  void   Get(int_4*  x, size_t n) {GetI4s(x,n);}
-  void   Get(uint_8* x, size_t n) {GetU8s(x,n);}
-  void   Get(int_8*  x, size_t n) {GetI8s(x,n);}
-
-  int    Version() {return version;}
-  string CreationDate() { return creationdate; }
-
-protected:
-  void      Scan();
-  char*     GetCStr(uint_2 l);
-#ifdef RFIO
-  erosifstream *s;
-#else
-  istream* s;
-#endif
-  int bigEndian;
-  int version;
-
-  string fName;
-  string creationdate;
-
-  struct PPFTag {
-    int_8 popos;
-    int_4 cid;
-    int_4 key;
-    uint_2 lnom;
-    char* nom;
-  };    
-  PPFTag* mTags;
-  int_4 mNTags;
-  list<char*> mSbuffs;
-  char* mSbuf;
-  int mSbsz;
-};
-
-class POutPersist {
-public:
-  POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE);
-  ~POutPersist();
-
-  int_4 WriteTag(int_4 key, char const * name=NULL);
-  void PutByte (char c);
-  void PutBytes(void const* ptr, size_t bytes);
-  void PutR4   (r_4);
-  void PutR4s  (r_4 const*, size_t);
-  void PutR8   (r_8);
-  void PutR8s  (r_8 const*, size_t);
-  void PutI2   (int_2);
-  void PutI2s  (int_2 const*, size_t);
-  void PutU2   (uint_2);
-  void PutU2s  (uint_2 const*, size_t);
-  void PutI4   (int_4);
-  void PutI4s  (int_4 const*, size_t);
-  void PutU4   (uint_4);
-  void PutU4s  (uint_4 const*, size_t);
-  void PutI8   (int_8);
-  void PutI8s  (int_8 const*, size_t);
-  void PutU8   (uint_8);
-  void PutU8s  (uint_8 const*, size_t);
-  void PutLine (char const* ptr, size_t len=0);
-
-  void   Put(char   c) {PutByte(c);}
-  void   Put(r_4    x) {PutR4(x);}
-  void   Put(r_8    x) {PutR8(x);}
-  void   Put(uint_2 x) {PutU2(x);}
-  void   Put(int_2  x) {PutI2(x);}
-  void   Put(uint_4 x) {PutU4(x);}
-  void   Put(int_4  x) {PutI4(x);}
-  void   Put(uint_8 x) {PutU8(x);}
-  void   Put(int_8  x) {PutI8(x);}
-  void   Put(r_4 const*    x, size_t n) {PutR4s(x,n);}
-  void   Put(r_8 const*    x, size_t n) {PutR8s(x,n);}
-  void   Put(uint_2 const* x, size_t n) {PutU2s(x,n);}
-  void   Put(int_2 const*  x, size_t n) {PutI2s(x,n);}
-  void   Put(uint_4 const* x, size_t n) {PutU4s(x,n);}
-  void   Put(int_4 const*  x, size_t n) {PutI4s(x,n);}
-  void   Put(uint_8 const* x, size_t n) {PutU8s(x,n);}
-  void   Put(int_8 const*  x, size_t n) {PutI8s(x,n);}
-
-
-protected:
-#ifdef RFIO
-  erosofstream *s;
-#else
-  ostream* s;
-#endif
-  int bigEndian;
-  int_4 numTag;
-  int_8 previous;
-};
-
-/* 
-// Ceci est dangereux car un template a priorite sur un changement de type, meme trivial...
-
-template <class T>
-POutPersist& operator << (POutPersist& c, T const& data)
-{
-  c.PutBytes(&data, sizeof(T));
-  return c;
-}
-
-template <class T>
-PInPersist& operator >> (PInPersist& c, T& data)
-{
-  c.GetBytes(&data, sizeof(T));
-  return c;
-}
-*/
-
+
+
+
+  // Ancestor for PInPersist and POutPersist
+  // Handles (statically) the registration of classes.
+
+  class PIOPersist {
+  public:
+    enum                         {PPS_NATIVE = -1, PPS_LITTLE_ENDIAN = 0, PPS_BIG_ENDIAN = 1};
+    typedef PPersist*            (*ClassCreatorFunc)();
+  
+    static void                  RegisterClass(uint_8 classId, ClassCreatorFunc f);
+    static ClassCreatorFunc      FindCreatorFunc(uint_8 classId);
+    static uint_8 Hash(string const& typname) {
+	MD5Init(&ctx);
+	MD5Update(&ctx, (unsigned char*) typname.c_str(), typname.size());
+	MD5Final(&ctx);
+	return ( *((uint_8*) ctx.digest) + *((uint_8*) (ctx.digest+8)));
+    }
+    static MD5_CTX ctx;
+  
+  private:
+
+    typedef map<uint_8, ClassCreatorFunc, less<uint_8> > ClassList;  
+    static ClassList             classList;
+
+  protected:
+    enum {PPS_NULL = 0,             // this is a null object
+	  PPS_STRING = 1,           // string, length (2b) + data
+	  PPS_OBJECT = 2,           // classId, data...
+	  PPS_REFERENCE = 3,        // objectId
+          PPS_TAG = 4,              // tag entries
+	  PPS_EOF = 5,              // Just before tag infomation, offset to PPS_TAG
+	  PPS_LINE = 6,             // '\n'-terminated, deprecated ?
+          PPS_SIMPLE = 16,          // 16 + number of bytes, up to 8 bytes
+          PPS_SIMPLE_ARRAY = 32,    // 32 + number of bytes, up to 8 bytes, then 2 bytes of length
+          PPS_SIMPLE_ARRAY4 = 64,   // 64 + number of bytes, up to 8 bytes, then 4 bytes of length
+          PPS_SIMPLE_ARRAY8 = 128   // 64 + number of bytes, up to 8 bytes, then 8 bytes of length
+   };
+
+    map<string, int_8> tags;
+  };
+
+
+  // TBD : use hash tables instead of maps. Check hashtbl status in STL.
+
+  class PInPersist : public PIOPersist {
+  public:
+    PInPersist(string const& flnm, bool scan=true);
+    ~PInPersist();
+
+    bool   GotoTag(string const& name);
+
+    void   GetByte (char& c);
+    void   GetBytes(void* ptr, size_t bytes);
+    void   GetR4   (r_4&);
+    void   GetR4s  (r_4*, size_t);
+    void   GetR8   (r_8&);
+    void   GetR8s  (r_8*, size_t);
+    void   GetI2   (int_2&);
+    void   GetI2s  (int_2*, size_t);
+    void   GetU2   (uint_2&);
+    void   GetU2s  (uint_2*, size_t);
+    void   GetI4   (int_4&);
+    void   GetI4s  (int_4*, size_t);
+    void   GetU4   (uint_4&);
+    void   GetU4s  (uint_4*, size_t);
+    void   GetI8   (int_8&);
+    void   GetI8s  (int_8*, size_t);
+    void   GetU8   (uint_8&);
+    void   GetU8s  (uint_8*, size_t);
+    void   GetLine (char* ptr, size_t len);
+    void   GetStr  (string&);
+
+    void   Get(char&   c) {GetByte(c);}
+    void   Get(r_4&    x) {GetR4(x);}
+    void   Get(r_8&    x) {GetR8(x);}
+    void   Get(uint_2& x) {GetU2(x);}
+    void   Get(int_2&  x) {GetI2(x);}
+    void   Get(uint_4& x) {GetU4(x);}
+    void   Get(int_4&  x) {GetI4(x);}
+    void   Get(uint_8& x) {GetU8(x);}
+    void   Get(int_8&  x) {GetI8(x);}
+    void   Get(r_4*    x, size_t n) {GetR4s(x,n);}
+    void   Get(r_8*    x, size_t n) {GetR8s(x,n);}
+    void   Get(uint_2* x, size_t n) {GetU2s(x,n);}
+    void   Get(int_2*  x, size_t n) {GetI2s(x,n);}
+    void   Get(uint_4* x, size_t n) {GetU4s(x,n);}
+    void   Get(int_4*  x, size_t n) {GetI4s(x,n);}
+    void   Get(uint_8* x, size_t n) {GetU8s(x,n);}
+    void   Get(int_8*  x, size_t n) {GetI8s(x,n);}
+    void   Get(string& x) {GetStr(x);}
+  
+    PPersist*  ReadObject();
+
+
+    int    Version() {return version;}
+    time_t CreationDate() { return creationdate; }
+
+  protected:
+    void   CheckTag   (short datasz);
+    void   CheckArrayTag(short datasz, size_t sz);
+    void   GetRawByte (char& c);
+    void   GetRawBytes(void* ptr, size_t bytes);
+    void   GetRawI2   (int_2&);
+    void   GetRawI4   (int_4&);
+    void   GetRawI8   (int_8&);
+    void   GetRawU8   (uint_8&);
+    void   GetObject(PPersist*);               // Object has been allocated with correct type
+    int_4  assignObjectId(PPersist* x);
+    void   Scan();
+    char*  GetCStr(uint_2 l);
+
+    istream* s;
+
+    bool bigEndian;
+    int version;
+
+    time_t creationdate;
+
+    // already read objects, id = order in array 
+    typedef vector<PPersist*> ObjList;
+    ObjList objList;
+
+    friend class PPersist;
+  };
+
+  class POutPersist : public PIOPersist {
+  public:
+    POutPersist(string const& flnm, int endianness = PPS_NATIVE);
+    ~POutPersist();
+
+    void WriteTag(string const& name);
+  
+    void PutByte (char c);
+    void PutBytes(void const* ptr, size_t bytes);
+    void PutR4   (r_4);
+    void PutR4s  (r_4 const*, size_t);
+    void PutR8   (r_8);
+    void PutR8s  (r_8 const*, size_t);
+    void PutI2   (int_2);
+    void PutI2s  (int_2 const*, size_t);
+    void PutU2   (uint_2);
+    void PutU2s  (uint_2 const*, size_t);
+    void PutI4   (int_4);
+    void PutI4s  (int_4 const*, size_t);
+    void PutU4   (uint_4);
+    void PutU4s  (uint_4 const*, size_t);
+    void PutI8   (int_8);
+    void PutI8s  (int_8 const*, size_t);
+    void PutU8   (uint_8);
+    void PutU8s  (uint_8 const*, size_t);
+    void PutLine (char const* ptr, size_t len=0); // deprecated ?
+    void PutStr  (string const&);
+    void PutObject (PPersist const*); // Like doing Write(stream) on object
+
+    void   Put(char   c) {PutByte(c);}
+    void   Put(r_4    x) {PutR4(x);}
+    void   Put(r_8    x) {PutR8(x);}
+    void   Put(uint_2 x) {PutU2(x);}
+    void   Put(int_2  x) {PutI2(x);}
+    void   Put(uint_4 x) {PutU4(x);}
+    void   Put(int_4  x) {PutI4(x);}
+    void   Put(uint_8 x) {PutU8(x);}
+    void   Put(int_8  x) {PutI8(x);}
+    void   Put(r_4 const*    x, size_t n) {PutR4s(x,n);}
+    void   Put(r_8 const*    x, size_t n) {PutR8s(x,n);}
+    void   Put(uint_2 const* x, size_t n) {PutU2s(x,n);}
+    void   Put(int_2 const*  x, size_t n) {PutI2s(x,n);}
+    void   Put(uint_4 const* x, size_t n) {PutU4s(x,n);}
+    void   Put(int_4 const*  x, size_t n) {PutI4s(x,n);}
+    void   Put(uint_8 const* x, size_t n) {PutU8s(x,n);}
+    void   Put(int_8 const*  x, size_t n) {PutI8s(x,n);}
+    void   Put(string const& s) {PutStr(s);}
+    void   Put(PPersist const* x) {PutObject(x);}
+
+
+  protected:
+    ostream* s;
+    bool bigEndian;
+
+    void     PutArrayTag(short datasz, size_t sz);
+    void     PutRawByte (char);
+    void     PutRawI2   (int_2);
+    void     PutRawI4   (int_4);
+    void     PutRawI8   (int_8);
+    void     PutRawU8   (uint_8);
+    void     PutRawBytes(void const* ptr, size_t bytes);
+    bool     serializeNullAndRepeat(PPersist const* x);
+    int_4    findObjectId(PPersist const* x);
+    int_4    assignObjectId(PPersist const* x);
+
+    // already serialized objects
+    typedef map<PPersist const*, int_4, less<PPersist const*> >  ObjList;
+    ObjList objList;
+  };
+  
+  
 #define RAWPERSISTIO(_Type_,_xtyp_)                                             \
-inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
-{                                                                               \
-  c.Put##_xtyp_(data);                                                        \
-  return c;                                                                     \
-}                                                                               \
+  inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
+  {                                                                               \
+    c.Put##_xtyp_(data);                                                          \
+    return c;                                                                     \
+  }                                                                               \
                                                                                 \
-inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
-{                                                                               \
-  c.Get##_xtyp_(data);                                                        \
-  return c;                                                                     \
-}                                                                               
-
-RAWPERSISTIO(int_4,I4)
-RAWPERSISTIO(uint_4,U4)
-RAWPERSISTIO(int_2,I2)
-RAWPERSISTIO(uint_2,U2)
-RAWPERSISTIO(char,Byte)
-RAWPERSISTIO(r_4,R4)
-RAWPERSISTIO(r_8,R8)
-
+  inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
+  {                                                                               \
+    c.Get##_xtyp_(data);                                                          \
+    return c;                                                                     \
+  }                                                                               
+
+  RAWPERSISTIO(int_4,I4);
+  RAWPERSISTIO(uint_4,U4);
+  RAWPERSISTIO(int_2,I2);
+  RAWPERSISTIO(uint_2,U2);
+  RAWPERSISTIO(char,Byte);
+  RAWPERSISTIO(r_4,R4);
+  RAWPERSISTIO(r_8,R8);
+  
 #if 0
 #define STRUCTPERSISTIO(_Type_, _field_, _size_)                                \
-inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
-{                                                                               \
-  c.PutBytes(&data._field_, _size_);                                            \
-  return c;                                                                     \
-}                                                                               \
+  inline POutPersist& operator << (POutPersist& c, _Type_ const& data)            \
+  {                                                                               \
+    c.PutBytes(&data._field_, _size_);                                            \
+    return c;                                                                     \
+  }                                                                               \
                                                                                 \
-inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
-{                                                                               \
-  c.GetBytes(&data._field_, _size_);                                            \
-  return c;                                                                     \
-}                                                                               
+  inline PInPersist& operator >> (PInPersist& c, _Type_& data)                    \
+  {                                                                               \
+    c.GetBytes(&data._field_, _size_);                                            \
+    return c;                                                                     \
+  }                                                                               
 
 #endif
-
-inline POutPersist& operator << (POutPersist& c, PPersist const& obj)
-{
-  obj.Write(c);
-  return c;
-}
-
-inline PInPersist& operator >> (PInPersist& c, PPersist& obj)
-{
-  obj.Read(c);
-  return c;
-}
-
-// Fabrication de fonction Create automatique, et enregistrement...
-template <class T>
-class PPersistRegistrar {
-public:
-  static PPersist* Create() {return new T();}
-  static void Register() {PPersistMgr::RegisterClass(T::classId,Create);}
-};
-
+  
+  inline POutPersist& operator << (POutPersist& c, PPersist const& obj)
+    {
+      obj.Write(c);
+      return c;
+    }
+  
+  inline PInPersist& operator >> (PInPersist& c, PPersist& obj)
+    {
+      obj.Read(c);
+      return c;
+    }
+  
+  // Utility class to
+  //   - compute the class ID from a MD5 hash of the class name
+  //   - register classes with PIOPersist, through PPRegister macro
+  
+  template <class T>
+    class PPersistRegistrar {
+    public:
+      static PPersist* Create() {return new T();}
+      static void Register() {PIOPersist::RegisterClass(Hash(),Create);}
+      static uint_8 Hash() {
+	return PIOPersist::Hash(typeid(T).name());
+      }
+    };
+  
 #define PPRegister(className) PPersistRegistrar<className>::Register();
+  
+} // namespace
 
 #endif
