Index: trunk/SophyaLib/BaseTools/ppersist.cc
===================================================================
--- trunk/SophyaLib/BaseTools/ppersist.cc	(revision 754)
+++ trunk/SophyaLib/BaseTools/ppersist.cc	(revision 802)
@@ -5,4 +5,5 @@
 #include "pexceptions.h"
 #include "ppersist.h"
+#include "anydataobj.h"
 #include <fstream.h>
 #include <iostream.h>
@@ -13,4 +14,11 @@
 #include "unixmac.h"
 #include <SIOUX.h>
+#endif
+
+//  strptime n'est pas defini sous Linux  - Reza Mars 2000
+#if defined(OS_LINUX)
+extern "C" {
+char *strptime(char *buf, const char *format, const struct tm *tm);
+}
 #endif
 
@@ -35,6 +43,7 @@
 
 MD5_CONTEXT PIOPersist::ctx;
-PIOPersist::ClassList * PIOPersist::classList = NULL;   // $CHECK$ Reza 26/04/99
-map<string, uint_8> * PIOPersist::typeids = NULL;
+PIOPersist::ClassList * PIOPersist::ppclassList = NULL;   // $CHECK$ Reza 26/04/99
+map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
+map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
 
 //++
@@ -44,36 +53,119 @@
 //--
 {
-classList = new PIOPersist::ClassList;
-typeids = new map<string, uint_8>;
-}
-
-//++
-void
-PIOPersist::RegisterClass(uint_8 classId, string typname, ClassCreatorFunc f)
+ppclassList = new PIOPersist::ClassList;
+ppclassNameList = new map<string, uint_8>;
+dobjclassNameList = new map<string, uint_8>;
+}
+
+//++
+void
+PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
 //
-//	Register a new persistant class.
-//	The classId is usually a hash of the class name, and this
-//	method is called only through the PPersistRegistrar template
-//	class, with the PPRegister(className) macro.
+//	Register a new persistence handler (PPersist) class.
+//	The classId is usually a hash of the class name, and
+//	ppclass_name is typeid(PPersistClass).name() .
+//	This method is called only through the PPersistRegistrar template
 //
 //--
 {
-  if (classList->size() && (classList->find(classId) != classList->end())) {
-      cerr << "RegisterClass : Error, " << hex << classId << dec 
-           << " already registered." << endl;
-      throw(DuplicateIdExc("PIOPersist::RegisterClass"));
+  if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
+    cerr << "RegisterClass : Error, " << hex << classId << dec 
+	 << " already registered." << endl;
+    throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass"));
+  }
+  if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
+    cerr << "RegisterClass : Error (2) " <<  ppclass_name 
+	 << " already registered." << endl;
+      throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass (3)"));
     }
   
-  (*classList)[classId] = f;
-  (*typeids)[typname]  = classId;
-}
-
+  (*ppclassList)[classId] = f;
+  (*ppclassNameList)[ppclass_name]  = classId;
+}
+
+//++
+void
+PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
+//	Register a new DataObj class corresponding to a PPersist classId
+//	class_typename should be typeid(DataObject).name() 
+//--
+{
+  if (ppclassList->find(classId) == ppclassList->end() ) 
+    throw( NotFoundExc("PIOPersist::RegisterDataObjClass() Not found classId") );
+  if (dobjclassNameList->size() && (dobjclassNameList->find(class_name) != dobjclassNameList->end())) 
+      throw(DuplicateIdExc("PIOPersist::RegisterDataObjClass"));
+
+  (*dobjclassNameList)[class_name]  = classId;
+}
+
+//	class_typename should be typeid(DataObject).name(), to be 
+//	used by POutPersist::PutDataObject() methods.
 
 PIOPersist::ClassCreatorFunc
 PIOPersist::FindCreatorFunc(uint_8 classId)
-{
-  ClassList::iterator i = classList->find(classId);
-  if (i == classList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
+// Returns the PPersist class creator function for the specified classId
+{
+  ClassList::iterator i = ppclassList->find(classId);
+  if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
   return (*i).second;
+}
+
+string 
+PIOPersist::getPPClassName(uint_8 classId)
+// Returns the PPersist class name for the specified classId
+{
+  map<string, uint_8>::iterator i;
+  for (i= ppclassNameList->begin(); i != ppclassNameList->end(); i++)
+    if ( (*i).second == classId ) return (*i).first;
+
+  throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
+}
+
+uint_8
+PIOPersist::getPPClassId(string const & typ_name)
+// Returns the classId for the specified PPersist class type name
+{
+  map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
+  if (i == ppclassNameList->end()) 
+    throw(NotFoundExc("PIOPersist::getPPClassId() Not found className"));
+  return (*i).second;
+}
+
+uint_8
+PIOPersist::getPPClassId(PPersist const & ppo)
+// Returns the classId for the specified PPersist class 
+{
+  string typ_name = typeid(ppo).name() ;
+  return (getPPClassId(typ_name) );
+}
+
+
+string 
+PIOPersist::getDataObjClassName(uint_8 classId)
+// Returns the PPersist class name for the specified classId
+{
+  map<string, uint_8>::iterator i;
+  for (i= dobjclassNameList->begin(); i != dobjclassNameList->end(); i++)
+    if ( (*i).second == classId ) return (*i).first;
+
+  throw(NotFoundExc("PIOPersist::getDataObjClassName() Not found classId"));
+}
+
+uint_8
+PIOPersist::getDataObjClassId(string const & typ_name)
+// Returns the classId for the specified PPersist class type name
+{
+  map<string, uint_8>::iterator i = dobjclassNameList->find(typ_name);
+  if (i == dobjclassNameList->end()) 
+    throw(NotFoundExc("PIOPersist::getDataObjClassId() Not found className"));
+  return (*i).second;
+}
+
+uint_8
+PIOPersist::getDataObjClassId(AnyDataObj const & o)
+// Returns the classId for the specified PPersist class 
+{
+  string typ_name = typeid(o).name() ;
+  return (getDataObjClassId(typ_name) );
 }
 
@@ -140,5 +232,5 @@
 //--
 {
-   s.PutObject(this);
+   s.PutPPObject(this);
 }
 
@@ -156,19 +248,31 @@
   // We should be the exact type  
   // Check tag value
-  char ppstype;
+  unsigned char ppstype,ppstag;
   s.GetTypeTag(ppstype);
-  if (ppstype != PInPersist::PPS_OBJECT) {
-    throw FileFormatExc("PPersist::Read : not an object in flow");
-  }
-  
-  // Check class id
-  uint_8 classId;
-  s.GetRawU8(classId);
-  uint_8 myClassId = PIOPersist::getTypeId(typeid(*this).name());
-  if (classId != myClassId) {
-    throw FileFormatExc("PPersist::Read : not the same object type");
-  }
-
-  ReadSelf(s);
+  if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
+  }
+  if (ppstype == PInPersist::PPS_OBJECT) {
+    // Check class id
+    uint_8 classId;
+    s.GetRawU8(classId);
+    uint_8 oid,oid2;
+    s.GetRawU8(oid);
+    if (classId != PIOPersist::getPPClassId(*this) )
+      throw FileFormatExc("PPersist::Read (): not the same object type");  
+    ReadSelf(s);
+    // Read the ENDOBJECT 
+    s.GetRawUByte(ppstag);
+    if (ppstag != PInPersist::PPS_ENDOBJECT)
+      throw FileFormatExc("PPersist::Read() No PPS_ENDOBJECT tag");
+    s.GetRawU8(oid2);
+    if (oid2 != oid)
+      throw FileFormatExc("PPersist::Read() Inconsistent PPS-OId at PPS_ENDOBJECT ");
+    s.KeepOId(oid, *this);   // Object should be kept with its PPS_OId  (if oid > 0)
+  }
+  else if ( ppstype == PInPersist::PPS_REFERENCE ) 
+    s.ReadReference(*this);
+
+  else  throw FileFormatExc("PPersist::Read() : not an object in flow");
+
 }
 
@@ -181,5 +285,5 @@
 {
   s.WriteTag(tag);
-  s.PutObject(this);
+  s.PutPPObject(this);
 }
 
@@ -196,4 +300,25 @@
 }
 
+// Renvoie l'identificateur de l'objet  - par defaut=0
+
+uint_8 
+PPersist::getMemOId() const
+{
+  return(0);
+}
+
+// Ces deux methodes doivent etre redefinies si   getMemOId() renvoie non nul (>0)
+// ShareDataReference() et CloneSharedReference()
+void 
+PPersist::ShareDataReference(PPersist & pcs)
+{
+  throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
+}
+
+PPersist *
+PPersist::CloneSharedReference()
+{
+  throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
+}
 
 //++
@@ -233,6 +358,11 @@
     throw FileFormatExc("PInPersist::PInPersist  bad header");
   }
-  version = atoi(rbuf+24);
-
+  rbuf[32] = '\0';
+  version = atoi(rbuf+25);
+  if (version < 2) {
+    cerr << "PInPersist::PInPersist(" << flnm << ") Version(=" << version 
+	 << ") < 2 not supported !" << endl;
+    throw FileFormatExc("PInPersist::PInPersist() - Unsupported (Old) Version");
+  }
   // read endianness
   GetRawBytes(rbuf, 32);
@@ -249,5 +379,5 @@
   rbuf[32] = '\0'; 
   struct tm tm;
-  #ifndef __MWERKS__
+  #ifndef __MWERKS__ 
   strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
   #else
@@ -258,5 +388,6 @@
   #endif
   creationdate = mktime(&tm);
-
+  filename = flnm;  // keep the filename
+  seqread = true;   // To flag non sequential reads
   if (scan) Scan();
 }
@@ -266,8 +397,19 @@
 PInPersist::~PInPersist()
 {
+  ObjList::iterator i;
+  for(i=objList.begin(); i!= objList.end(); i++)  
+    if ((*i).second)  delete (*i).second;
   delete s;
 }
 
 
+string 
+PInPersist::CreationDateStr()
+{
+  time_t cdt = CreationDate();
+  string cdate = ctime(&cdt);
+  return(cdate);
+}
+
 void
 PInPersist::Scan()
@@ -275,5 +417,5 @@
   // On cherche la liste des tags, a la fin du fichier
 
-  char ppstype;
+  unsigned char ppstype;
   size_t debut;
 #ifdef STREAMPOS_IS_CLASS
@@ -333,5 +475,6 @@
       //    throw NotFoundExc("PInPersist::GotoTag   tag not found");
   s->seekg((*i).second);
-  objList.clear(); // $CHECK$ EA 171199
+  seqread = false;
+  //  objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
   return(true); 
 }
@@ -344,5 +487,5 @@
   for (int j=0; j<itag; j++) i++;
   s->seekg((*i).second);
-  objList.clear(); // $CHECK$ EA 171199
+  // objList.clear();  $CHECK$ EA 171199  Ne pas faire ? Reza 03/2000 ?
   return(true);
 }
@@ -355,4 +498,16 @@
   for (int j=0; j<itag; j++) i++;
   return((*i).first);
+}
+
+string
+PInPersist::GetTagClassName(int itag)
+{
+  // A faire
+//   if (itag<0 || itag >= (int)tags.size()) return "";
+//   map<string, int_8>::iterator i = tags.begin();
+//   for (int j=0; j<itag; j++) i++;
+//   uint_8 cid = (*i).second;
+//   return(GetClassName(cid));
+  return("");
 }
 
@@ -424,11 +579,12 @@
 
 void
-PInPersist::GetTypeTag(char& c) 
-{
-  GetRawByte(c);
-  while (c == PPS_TAG_MARK) {
-    objList.clear();
-    GetRawByte(c);
-  }
+PInPersist::GetTypeTag(unsigned char& c) 
+{
+  c = PPS_TAG_MARK;
+  while (c == PPS_TAG_MARK) GetRawUByte(c);
+  //  while (c == PPS_TAG_MARK) {    Il ne faut plus faire ca !
+  //    objList.clear();             $CHECK$ Reza 03/2000
+  //    GetRawByte(c);
+  //  }
 }
 
@@ -441,4 +597,10 @@
 
 void
+PInPersist::GetRawUByte(unsigned char& c)
+{
+  GetRawBytes(&c, 1);
+}
+
+void
 PInPersist::GetRawBytes(void* ptr, size_t bytes)
 {
@@ -479,36 +641,33 @@
 
 void
-PInPersist::CheckTag(short datasz)
-{
-  char ppstype;
+PInPersist::CheckTag(short datasz, short datatype)
+// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
+{
+  unsigned char ppstype;
   GetTypeTag(ppstype);
-  if (ppstype != PPS_SIMPLE + datasz)
+  if (ppstype != PPS_SIMPLE + datasz + datatype)
     throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
 }
 
 void
-PInPersist::CheckArrayTag(short datasz, size_t sz)
-{
-  char ppstype;
+PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
+// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
+{
+  unsigned char ppstype;
   GetTypeTag(ppstype);
   size_t filesz;
-  if (sz <= 0x7fff) {
-    if (ppstype != PPS_SIMPLE_ARRAY + datasz)
-      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
-    int_2 ff;
-    GetRawI2(ff); filesz=ff;
-  } else if (sz <= 0x7fffffff) {
-    if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
-      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+  if (sz <= 0x7fffffff) {
+    if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
+      throw FileFormatExc("PInPersist::CheckArrayTag   bad type in ppersist file");
     int_4 ff;
     GetRawI4(ff); filesz=ff;
   } else {
-    if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
-      throw FileFormatExc("PInPersist::CheckTag   bad type in ppersist file");
+    if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
+      throw FileFormatExc("PInPersist::CheckArrayTag   bad type in ppersist file");
     uint_8 ff;
     GetRawU8(ff); filesz=ff;
   }
   if (filesz != sz)
-    throw FileFormatExc("PInPersist::CheckTag   bad array size in ppersist file");
+    throw FileFormatExc("PInPersist::CheckArrayTag   bad array size in ppersist file");
 }
 
@@ -516,12 +675,13 @@
 PInPersist::GetByte(char& c)
 {
-  CheckTag(1);
+  CheckTag(1,PPS_DATATYPE_CHAR);
   GetRawBytes(&c, 1);
 }
 
+
 void
 PInPersist::GetBytes(void* ptr, size_t bytes)
 {
-  CheckArrayTag(1, bytes);
+  CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
   GetRawBytes(ptr, bytes);
 }
@@ -529,5 +689,5 @@
 PInPersist::GetR4   (r_4& result)
 {
-  CheckTag(4);
+  CheckTag(4,PPS_DATATYPE_FLOAT);
   GetRawBytes(&result, sizeof(r_4));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -539,5 +699,5 @@
 PInPersist::GetR4s  (r_4* tab, size_t n)
 {
-  CheckArrayTag(4,n);
+  CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
   GetRawBytes(tab, n*sizeof(r_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -552,5 +712,5 @@
 PInPersist::GetR8   (r_8& result)
 {
-  CheckTag(8);
+  CheckTag(8,PPS_DATATYPE_FLOAT);
   GetRawBytes(&result, sizeof(r_8));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -561,5 +721,5 @@
 PInPersist::GetR8s  (r_8* tab, size_t n)
 {
-  CheckArrayTag(8,n);
+  CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
   GetRawBytes(tab, n*sizeof(r_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -574,5 +734,5 @@
 PInPersist::GetI2   (int_2& result)
 {
-  CheckTag(2);
+  CheckTag(2,PPS_DATATYPE_INTEGER);
   GetRawBytes(&result, sizeof(int_2));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -583,5 +743,5 @@
 PInPersist::GetI2s  (int_2* tab, size_t n)
 {
-  CheckArrayTag(2,n);
+  CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
   GetRawBytes(tab, n*sizeof(int_2));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -596,5 +756,5 @@
 PInPersist::GetU2   (uint_2& result)
 {
-  CheckTag(2);
+  CheckTag(2,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(&result, sizeof(uint_2));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -605,5 +765,5 @@
 PInPersist::GetU2s  (uint_2* tab, size_t n)
 {
-  CheckArrayTag(2,n);
+  CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(tab, n*sizeof(uint_2));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -618,5 +778,5 @@
 PInPersist::GetI4   (int_4& result)
 {
-  CheckTag(4);
+  CheckTag(4,PPS_DATATYPE_INTEGER);
   GetRawBytes(&result, sizeof(int_4));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -627,5 +787,5 @@
 PInPersist::GetI4s  (int_4* tab, size_t n)
 {
-  CheckArrayTag(4,n);
+  CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
   GetRawBytes(tab, n*sizeof(int_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -640,5 +800,5 @@
 PInPersist::GetU4   (uint_4& result)
 {
-  CheckTag(4);
+  CheckTag(4,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(&result, sizeof(uint_4));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -649,5 +809,5 @@
 PInPersist::GetU4s  (uint_4* tab, size_t n)
 {
-  CheckArrayTag(4,n);
+  CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(tab, n*sizeof(uint_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -663,5 +823,5 @@
 PInPersist::GetI8   (int_8& result)
 {
-  CheckTag(8);
+  CheckTag(8,PPS_DATATYPE_INTEGER);
   GetRawBytes(&result, sizeof(int_8));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -672,5 +832,5 @@
 PInPersist::GetI8s  (int_8* tab, size_t n)
 {
-  CheckArrayTag(8,n);
+  CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
   GetRawBytes(tab, n*sizeof(int_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -685,5 +845,5 @@
 PInPersist::GetU8   (uint_8& result)
 {
-  CheckTag(8);
+  CheckTag(8,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(&result, sizeof(uint_8));
   if (bigEndian != IS_BIG_ENDIAN)
@@ -694,5 +854,5 @@
 PInPersist::GetU8s  (uint_8* tab, size_t n)
 {
-  CheckArrayTag(8,n);
+  CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
   GetRawBytes(tab, n*sizeof(uint_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
@@ -708,9 +868,8 @@
 PInPersist::GetLine(char* ptr, size_t len)
 {
-  char ppstype;
-  GetTypeTag(ppstype);
-  if (ppstype != PPS_LINE) 
-    throw FileFormatExc("PInPersist::GetLine   bad type in ppersist file");
-  s->getline(ptr, len, '\n');
+  string str;
+  GetStr(str);
+  strncpy(ptr, str.c_str(), len);
+  ptr[len] = '\0';
 }
 
@@ -718,10 +877,10 @@
 PInPersist::GetStr(string& str)
 {
-  char ppstype;
+  unsigned char ppstype;
   GetTypeTag(ppstype);
   if (ppstype != PPS_STRING) 
-    throw FileFormatExc("PInPersist::GetLine   bad type in ppersist file");
-  int_2 len;
-  GetRawI2(len);
+    throw FileFormatExc("PInPersist::GetStr   bad type in ppersist file");
+  int_4 len;
+  GetRawI4(len);
   char * buff = new char[len+1];
   GetRawBytes(buff, len);
@@ -731,9 +890,31 @@
 }
 
+
 PPersist*
 PInPersist::ReadObject()
 {
+  return(GetPPObject());
+}
+
+void 
+PInPersist::GetObject(AnyDataObj & o)
+{
+  GetPPObject(&o);
+  return;
+}
+
+void 
+PInPersist::GetObject(AnyDataObj & o, string tagname)
+{
+  GotoTag(tagname);
+  GetPPObject(&o);
+  return;
+}
+
+PPersist*
+PInPersist::GetPPObject(AnyDataObj * po)
+{
   // Get tag
-  char ppstype;
+  unsigned char ppstype;
   GetTypeTag(ppstype);
   if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
@@ -747,4 +928,6 @@
     uint_8 classId;
     GetRawU8(classId);
+    uint_8 oid,oid2;
+    GetRawU8(oid);
     
     // Get factory method
@@ -756,25 +939,238 @@
     // Create object
     PPersist* object = f();
+    //  If a DataObject was specified , we assign it to the PPersistObject
+    if (po != NULL) object->SetDataObj(*po);
+
     object->ReadSelf(*this);
-    assignObjectId(object);
+    unsigned char ppstag;
+    // Read the ENDOBJECT 
+    GetRawUByte(ppstag);
+    if (ppstag != PPS_ENDOBJECT)
+      throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
+    GetRawU8(oid2);
+    if (oid2 != oid)
+      throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
+
+    KeepOId(oid, *object);
     return object;
-  } else {
-    // Get object id
-    int_4 id;
-    GetRawI4(id);
-    if (id <0 || id>=objList.size()) {
-      char msg[200];
-      sprintf(msg, "PInPersist::ReadObject    invalid object id for reference: %d/%d",id,objList.size());
-      throw FileFormatExc(msg);
+  } 
+  else if (ppstype == PPS_REFERENCE) 
+    return ReadReference();
+
+  else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");  
+}
+
+
+void
+PInPersist::AnalyseTags(int lev)
+{
+  unsigned char ppstag=0;
+  unsigned char ppst1,ppst2,ppst3;
+  uint_8 cpos,fsize;
+  uint_8 ui8,cid,oid;
+  int_4 i4;
+  int_8 i8;
+  char * buff;
+  string str;
+  
+  cout << "\n ---------------------------------------------------------- " << endl;
+  cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl; 
+
+
+#ifdef STREAMPOS_IS_CLASS
+  cpos = s->tellg().offset();
+#else
+  cpos = s->tellg();
+#endif
+  s->seekg(0,ios::end);
+#ifdef STREAMPOS_IS_CLASS
+  fsize = s->tellg().offset();
+#else
+  fsize = s->tellg();
+#endif
+  s->seekg(cpos,ios::beg);
+
+  cout << "   Version= " << Version() << " FileSize= " << fsize 
+       << " Creation Date= " << CreationDateStr() <<  endl;
+  
+  uint_8 totntags = 0;
+  bool eofok = false;
+
+  while ( (ppstag != PPS_EOF) &&  (cpos < fsize) ) {
+#ifdef STREAMPOS_IS_CLASS
+  cpos = s->tellg().offset();
+#else
+  cpos = s->tellg();
+#endif
+    GetRawUByte(ppstag);
+    totntags++;
+
+    ppst1 = ppstag&0x0f;  // bits 0123
+    ppst2 = ppstag&0x30;  // bits     45
+    ppst3 = ppstag&0xc0;  // bits       67
+    if ((ppst2 == 0) && (ppst3 == 0) ) {
+      switch (ppst1) {
+
+      case PPS_NULL :
+	if (lev > 1)  cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
+	break;
+
+      case PPS_STRING :
+	GetRawI4(i4);
+	if (lev > 1)  cout << "<PPS_STRING> tag at position " << hex << cpos << dec 
+			   << " Length=" << i4 << endl;
+	s->seekg(i4,ios::cur);
+	break;
+
+      case PPS_OBJECT :
+	GetRawU8(cid);
+	GetRawU8(oid);
+	cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid 
+	     << "  ObjectId= " << oid << dec << endl;
+	break;
+
+      case PPS_REFERENCE :
+	GetRawU8(oid);
+	GetRawI8(i8);
+	cout << "<PPS_REFERENCE> tag at position " << hex << cpos << "  ObjectId= " 
+	     << oid << "  OrigPos=" << i8 << dec << endl;
+	break;
+
+      case PPS_TAG_MARK :
+	cout << "<PPS_TAG_MARK> tag at position " << hex << cpos << dec << endl; 
+	break;
+     
+      case PPS_ENDOBJECT :
+	GetRawU8(oid);
+	cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << "  ObjectId= " 
+	     << oid << dec << endl;
+	break;
+
+      case PPS_TAG :
+	GetRawI8(i8);
+	GetRawI4(i4);
+	buff = new char[i4+1];
+	GetRawBytes(buff, i4); 
+        buff[i4] = '\0';  str = buff;
+	delete[] buff;
+	cout << "<PPS_TAG> tag at position " << hex << cpos << dec 
+	     << " Name= " << str << endl; 
+	break;
+
+      case PPS_EOF :
+	GetRawI8(i8);	
+	cout << "<PPS_EOF> tag at position " << hex << cpos  
+	     << " TagPos=" << i8 << dec << endl;
+	eofok = true;
+	break;
+
+      default :
+	cerr << " ERROR : Unexpected tag value " << hex << ppstag 
+	     << " At position" << cpos << dec << endl;
+	throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
+      }
     }
-    return objList[id];
-  }
-}
-
-int_4 
-PInPersist::assignObjectId(PPersist* x)
-{
-  objList.push_back(x);
-  return objList.size()-1;
+    else {
+      string dtype = "???? x";
+      if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
+      else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
+      else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
+      else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
+      int_4 dsize = ppst1;
+      char sb[16];
+      sprintf(sb, "%d", dsize);
+      dtype += sb;
+
+      switch (ppst2) {
+
+      case PPS_SIMPLE :
+	if (lev > 2)  cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec 
+			   << " DataType=" << dtype << endl;
+	s->seekg(dsize, ios::cur);
+	break;
+
+      case PPS_SIMPLE_ARRAY4 :
+	GetRawI4(i4);
+	if (lev > 0)  cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec 
+			   << " DataType=" << dtype << " NElts= " << i4 << endl;
+	s->seekg((uint_8)dsize*(uint_8)i4, ios::cur);
+	break;
+
+      case PPS_SIMPLE_ARRAY8 :
+	GetRawU8(ui8);
+	if (lev > 0)  cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec 
+			   << " DataType=" << dtype << " NElts= " << ui8 << endl;
+	s->seekg((uint_8)dsize*ui8, ios::cur);
+	break;
+      }
+    }
+  }
+  if (!eofok) 
+    throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
+
+  cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl; 
+  cout << " ---------------------------------------------------------- \n" << endl;
+  return;
+}
+
+void
+PInPersist::ReadReference(PPersist & ppo)
+{
+  PPersist * pr = ReadReference();
+  ppo.ShareDataReference(*pr);
+}
+
+
+PPersist *
+PInPersist::ReadReference()
+{
+  uint_8 oid;
+  int_8 pos;
+  GetRawU8(oid);
+  GetRawI8(pos);
+  //  cerr << " DBG - PInPersist::ReadReference-A "  << oid << " Pos= " << pos << endl; 
+  map<uint_8, PPersist *>::iterator i = objList.find(oid);
+  if (i != objList.end()) return (*i).second; 
+  else  {  // We may have skeeped it !
+    // Let's try to read it
+    int_8 cpos;
+#ifdef STREAMPOS_IS_CLASS
+    cpos = s->tellg().offset();
+#else
+    cpos = s->tellg();
+#endif
+    s->seekg(pos);
+    PPersist* ppo = ReadObject();
+    s->seekg(cpos);
+    delete ppo;
+    //    cerr << " DBG - PInPersist::ReadReference-B ... " << endl;  
+
+    map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
+    if (i2 == objList.end()) 
+      throw FileFormatExc("PInPersist::ReadReference()   Not found PPS_OId ");
+    return (*i2).second; 
+  }
+}
+
+
+void
+PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
+{
+  if ((oid&0x1) == 0)  return; // This is not an object which can be referenced
+  //  cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
+  if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
+    //  Ceci ne devrait arriver que si on lit dans le desordre (avec GotoTag)
+    //  et pas avec une lecture sequentielle ...   Reza 03/2000
+    //  cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
+    if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
+    PPersist *pp = (*objList.find(oid)).second;
+    ppo.ShareDataReference(*pp);
+  }
+  else {
+    PPersist * npp = ppo.CloneSharedReference(); 
+    if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
+    objList[oid] = npp;
+  }
+  return;
 }
 
@@ -803,9 +1199,11 @@
     bigEndian = endianness;
 
+  // PPS (POutPersist stream) Object Id initialisation
+  pps_OId = 0;
   // Output stream creation
   s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);  
 
   // Header
-  PutRawBytes("SOS-SOPHYA-PPersistFile V1               ",32);
+  PutRawBytes("SOS-SOPHYA-PPersistFile V2               ",32);
   PutRawBytes(bigEndian 
 	   ? "BIG-ENDIAN                             "
@@ -819,4 +1217,5 @@
   datestring[32] = '\0'; 
   PutRawBytes(datestring, 32);
+  filename = flnm;
 }
 
@@ -824,5 +1223,5 @@
 {
   if (tags.size() == 0) {
-    PutRawByte(PPS_EOF);
+    PutRawUByte(PPS_EOF);
     PutRawI8(-1);
   } else {
@@ -836,10 +1235,10 @@
       string name = (*i).first;
       int_8 pos = (*i).second;
-      PutRawByte(PPS_TAG);                       // This is a tag
+      PutRawUByte(PPS_TAG);                       // This is a tag
       PutRawI8(pos);                             // position of previous tag
       PutRawI4(name.length());                   // length of the name
       PutRawBytes(name.c_str(), name.length());  // name, without final "0".
     }
-    PutRawByte(PPS_EOF);
+    PutRawUByte(PPS_EOF);
     PutRawI8(tagPos);
   }
@@ -868,6 +1267,6 @@
 
   tags[name] = tagPos;
-  PutRawByte(PPS_TAG_MARK);                       // This is a tag
-  objList.clear(); // $CHECK$ EA 171199
+  PutRawUByte(PPS_TAG_MARK);                       // This is a tag
+  //  objList.clear(); // $CHECK$ EA 171199  - Ne pas faire ? Reza 03/2000
 }
 
@@ -914,4 +1313,10 @@
 
 void
+POutPersist::PutRawUByte(unsigned char c)
+{
+  PutRawBytes(&c, 1);
+}
+
+void
 POutPersist::PutRawI2   (int_2 val)
 {
@@ -950,14 +1355,12 @@
 
 void
-POutPersist::PutArrayTag(short datasz, size_t sz)
-{
-  if (sz <= 0x7fff) {
-    PutRawByte(PPS_SIMPLE_ARRAY + datasz);
-    PutRawI2(sz);
-  } else if (sz <= 0x7fffffff) {
-    PutRawByte(PPS_SIMPLE_ARRAY4 + datasz);
+POutPersist::PutArrayTag(short datasz, size_t sz, short datatype) 
+// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
+{
+  if (sz <= 0x7fffffff) {
+    PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
     PutRawI4(sz);
   } else {
-    PutRawByte(PPS_SIMPLE_ARRAY8 + datasz);
+    PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
     PutRawU8(sz);
   } 
@@ -967,5 +1370,5 @@
 POutPersist::PutByte(char c)
 {
-  PutRawByte(PPS_SIMPLE + 1);
+  PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
   PutRawBytes(&c, 1);
 }
@@ -976,5 +1379,5 @@
 POutPersist::PutBytes(void const* ptr, size_t bytes)
 {
-  PutArrayTag(1, bytes);
+  PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
   PutRawBytes(ptr, bytes);
 }
@@ -983,5 +1386,5 @@
 POutPersist::PutR4   (r_4 val)
 {
-  PutRawByte(PPS_SIMPLE + 4);
+  PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
   
   if (bigEndian != IS_BIG_ENDIAN)
@@ -994,5 +1397,5 @@
 POutPersist::PutR4s  (r_4 const* tab, size_t n)
 {
-  PutArrayTag(4, n);
+  PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1010,5 +1413,5 @@
 POutPersist::PutR8   (r_8 val)
 {
-  PutRawByte(PPS_SIMPLE + 8);
+  PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1021,5 +1424,5 @@
 POutPersist::PutR8s  (r_8 const* tab, size_t n)
 {
-  PutArrayTag(8, n);
+  PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1037,5 +1440,5 @@
 POutPersist::PutI2   (int_2 val)
 {
-  PutRawByte(PPS_SIMPLE + 2);
+  PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1048,5 +1451,5 @@
 POutPersist::PutI2s  (int_2 const* tab, size_t n)
 {
-  PutArrayTag(2, n);
+  PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
   
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1064,5 +1467,5 @@
 POutPersist::PutU2   (uint_2 val)
 {
-  PutRawByte(PPS_SIMPLE + 2);
+  PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1075,5 +1478,5 @@
 POutPersist::PutU2s  (uint_2 const* tab, size_t n)
 {
-  PutArrayTag(2, n);
+  PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1091,5 +1494,5 @@
 POutPersist::PutI4   (int_4 val)
 {
-  PutRawByte(PPS_SIMPLE + 4);
+  PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1102,5 +1505,5 @@
 POutPersist::PutI4s  (int_4 const* tab, size_t n)
 {
-  PutArrayTag(4, n);
+  PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1118,5 +1521,5 @@
 POutPersist::PutU4   (uint_4 val)
 {
-  PutRawByte(PPS_SIMPLE + 4);
+  PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1129,5 +1532,5 @@
 POutPersist::PutU4s  (uint_4 const* tab, size_t n)
 {
-  PutArrayTag(4, n);
+  PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1145,5 +1548,5 @@
 POutPersist::PutI8   (int_8 val)
 {
-  PutRawByte(PPS_SIMPLE + 8);
+  PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1156,5 +1559,5 @@
 POutPersist::PutI8s  (int_8 const* tab, size_t n)
 {
-  PutArrayTag(8, n);
+  PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1172,5 +1575,5 @@
 POutPersist::PutU8   (uint_8 val)
 {
-  PutRawByte(PPS_SIMPLE + 8);
+  PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian != IS_BIG_ENDIAN)
@@ -1183,5 +1586,5 @@
 POutPersist::PutU8s  (uint_8 const* tab, size_t n)
 {
-  PutArrayTag(8, n);
+  PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
 
   if (bigEndian == IS_BIG_ENDIAN) {
@@ -1199,6 +1602,6 @@
 POutPersist::PutStr(string const& str) 
 {
-  PutRawByte(PPS_STRING);
-  PutRawI2(str.length());
+  PutRawUByte(PPS_STRING);
+  PutRawI4(str.length());
   PutRawBytes(str.c_str(), str.length());
 }
@@ -1207,21 +1610,41 @@
 POutPersist::PutLine(char const* ptr, size_t len)
 {
-  PutRawByte(PPS_LINE);
-
-  if (len == 0)  len = strlen(ptr);
-  PutRawBytes(ptr, len);
-  PutRawByte('\n');
-}
-
-void
-POutPersist::PutObject(PPersist const* obj) 
-{
-  if (serializeNullAndRepeat(obj)) return;
-
-  PutRawByte(PPS_OBJECT);
-  PutRawU8(getTypeId(typeid(*obj).name()));
-  //PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
-  assignObjectId(obj);
+  string str = ptr;
+  PutStr(str);
+}
+
+
+void
+POutPersist::PutObject(AnyDataObj & o)
+{
+  ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
+  if (!f) 
+      throw NotFoundExc("PInPersist::PutObject()   class not registered");
+  PPersist* ppo = f();
+  ppo->SetDataObj(o);
+  PutPPObject(ppo);
+}
+
+void
+POutPersist::PutObject(AnyDataObj & o, string tagname)
+{
+  WriteTag(tagname);
+  PutObject(o);
+}
+
+
+void
+POutPersist::PutPPObject(PPersist const* obj) 
+{
+  if (serializeNullAndRepeat(obj)) return;  // NULL object or already written in stream
+
+  //   We have to write the object 
+  uint_8 oid = assignObjectId(obj);       // We assing a PPS Object Id 
+  PutRawUByte(PPS_OBJECT);         // We write the Object Tag
+  PutRawU8(getPPClassId(*obj));    // Writing the PPersist ClassId
+  PutRawU8(oid);                   // Write the PPS Object Id 
   obj->WriteSelf(*this);
+  PutRawUByte(PPS_ENDOBJECT);      // We write the End-Of-Object Tag
+  PutRawU8(oid);                   // and again its PPS Object Id 
 }
 
@@ -1230,33 +1653,55 @@
 {
   if (x == NULL) {
-    PutRawByte(PPS_NULL);
+    PutRawUByte(PPS_NULL);
     return true;
   }
 
-  int_4 id = findObjectId(x);
-  if (id >= 0) {
-    PutRawByte(PPS_REFERENCE);
-    PutRawI4(id);
+  int_8 pos;
+  uint_8 id = findObjectId(x, pos);
+  if (id > 0) {
+    PutRawUByte(PPS_REFERENCE);
+    PutRawU8(id);      // Writing the corresponding object Id
+    PutRawI8(pos);     // The original object position 
     return true;
   }
   
-  return false;
-}
-
-int_4 
+  return false;  // Object have to be written in stream ...
+}
+
+uint_8 
 POutPersist::assignObjectId(PPersist const* x)
 {
-  int_4 id = objList.size();
-  objList[x] = id;
+  pps_OId += 16;  // We keep the three first bytes for future usage
+                  // Bit 1 non zero -> Object can be referenced 
+  uint_8 id = pps_OId;
+  uint_8 mid = x->getMemOId();
+  if (mid > 0) {
+    int_8 pos;
+    if (findObjectId(x,pos) > 0)  
+      throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
+    id += 1;  // Object Id starting at zero
+    objreftag rt;
+    rt.ppsoid = id;
+#ifdef STREAMPOS_IS_CLASS
+    rt.ppspos = s->tellp().offset();
+#else
+    rt.ppspos = s->tellp();
+#endif
+    objList[mid] = rt;
+  }
   return id;
 }
 
-int_4 
-POutPersist::findObjectId(PPersist const* x)
-{
-  ObjList::iterator i = objList.find(x);
-  if (i == objList.end()) return -1;
-  return (*i).second;
-}
-
-
+uint_8 
+POutPersist::findObjectId(PPersist const* x, int_8 & pos)
+{
+  pos = -1;
+  uint_8 mid = x->getMemOId();
+  if (mid == 0)   return(0);
+  ObjList::iterator i = objList.find(mid);
+  if (i == objList.end()) return 0;
+  pos = (*i).second.ppspos;
+  return (*i).second.ppsoid;
+}
+
+
