Index: trunk/SophyaLib/BaseTools/ppersist.cc
===================================================================
--- trunk/SophyaLib/BaseTools/ppersist.cc	(revision 219)
+++ trunk/SophyaLib/BaseTools/ppersist.cc	(revision 241)
@@ -1,11 +1,9 @@
-#include "defs.h"
+#include "machdefs.h"
+#include "pexceptions.h"
 #include <stdio.h>
 #include "peidainit.h"
 #include "ppersist.h"
-#include "dates.h"
-
-#ifndef RFIO
 #include <fstream.h>
-#endif
+#include <typeinfo>
 
 
@@ -15,132 +13,58 @@
 #endif
 
-#if SWAP==1
-#define IS_BIG_ENDIAN 0
-#else
-#define IS_BIG_ENDIAN 1
-#endif
-
-//++
-// Class	PPersistMgr
+using namespace PlanckDPC;
+
+#define MAXTAGLEN 255
+
+//++
+// Class	PIOPersist
 // Lib		Outils++
 // include	ppersist.h
 //
-//	Classe gestionnaire d'objets persistants. Les méthodes statiques
-//	de cette classe permettent d'enregistrer des classes persistantes,
-//	et de relire automatiquement des objets.
-//--
-
-//++
-// Links	Voir
+//	Root class for persistant files. Handles the registration of
+//	persistant classes
+//--
+
+//++
+// Links	See
 // PPersist
-// PShPersist
-//--
-
-PPersistMgr::ClassList* PPersistMgr::classList = NULL;
-PShPersist::ObjList*    PShPersist::objList = NULL;
-
-//++
-void
-PPersistMgr::RegisterClass(int_4 classId, ClassCreatorFunc f, bool shared)
-//
-//	Enregistre une nouvelle classe auprès du gestionnaire. classId doit
-//	identifier de façon unique la classe. f doit créer un nouvel objet
-//	de cette classe (qui doit hériter de PPersist), non initialisé, et qui
-//	sera relu à partir du fichier d'objets persistants.
-//
-//	Si shared est true, la classe doit hériter de PShPersist, et la persistance
-//	gère le fait que plusieurs objets Xi puissent faire référence à un même objet A.
-//	A, qui hérite donc de PShPersist, ne sera écrit qu'une seule fois dans le fichier
-//	lorsque les Xi sont écrits, et la référence à A sera mise à jour lors de la lecture
-//	des Xi...
-//--
-{
-  DBASSERT(classList);
-  if (classList->size() && (classList->find(classId) != classList->end())) {
+// PInPersist
+// POutPersist
+//--
+
+
+MD5_CTX PIOPersist::ctx;
+PIOPersist::ClassList PIOPersist::classList;
+
+
+//++
+void
+PIOPersist::RegisterClass(uint_8 classId, 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.
+//
+//--
+{
+  if (classList.size() && (classList.find(classId) != classList.end())) {
       cerr << "RegisterClass : Error, " << hex << classId << dec 
            << " already registered." << endl;
-      THROW(dupIdErr);
+      throw(DuplicateIdExc("PIOPersist::RegisterClass"));
     }
   
-  ClassListEntry entry = {shared, f};
-  (*classList)[classId] = entry;
-}
-
-
-PPersistMgr::ClassCreatorFunc
-PPersistMgr::FindCreatorFunc(int_4 classId)
-{
-  DBASSERT(classList);
-  return (*classList)[classId].f;
-}
-
-PPersistMgr::ClassCreatorFunc
-PPersistMgr::FindCreatorFunc(int_4 classId, bool& isShared)
-{
-  DBASSERT(classList);
-  ClassListEntry entry = (*classList)[classId];
-  isShared = entry.shared;
-  return entry.f;
-}
-
-//++
-PPersist*
-PPersistMgr::ReadObject(PInPersist& s)
-//
-//	Lit un objet dans le stream s, en créant automatiquement un
-//	objet du bon type.
-//--
-{
-  DBASSERT(classList);
-  DBASSERT(PShPersist::objList);
-  // On commence par lire le type de l'objet
-  int_4 classId;
-  s >> classId;
-
-  // On recupere le createur, et on regarde si l'objet est partage
-  bool shared;
-  if (!classList->size() || (classList->find(classId) == classList->end())) {
-    cerr << "PPersistMgr::ReadObject Error : Class " << classId << " not registered" << endl;
-    THROW(notFoundErr);
-  }
-  PPersistMgr::ClassCreatorFunc f = FindCreatorFunc(classId, shared);
-  
-  if (!f) THROW(notFoundErr);
-  
-  PPersist* object;
-  if (shared) {
-    // Si l'objet est partage, ce qui suit est son identificateur, sur 4 octets
-    // et un octet ensuite qui dit si l'objet est present.
-  
-    int_4 objectId;
-    char objectSaved;
-    
-    s >> objectId >> objectSaved;
-
-#if 0
-    // On regarde si l'objet est deja en memoire
-    object = PShPersist::FindObject(objectId);
-    
-    // On verifie qu'on est dans une situation coherente...
-    if ((!objectSaved) == (!object)) THROW(inconsistentErr);
-#else
-    if (!objectSaved) {
-      object = PShPersist::FindObject(objectId);
-      if (!object) THROW(inconsistentErr);
-    }
-#endif
-    if (objectSaved) {
-      object = f();
-      object->ReadSelf(s);
-      ((PShPersist*)object)->mObjectID = objectId;
-      (*PShPersist::objList)[objectId] = (PShPersist*)object; 
-    }
-  } else {
-    object = f();
-    object->ReadSelf(s);
-  }
-  
-  return object;
-}
+  classList[classId] = f;
+}
+
+
+PIOPersist::ClassCreatorFunc
+PIOPersist::FindCreatorFunc(uint_8 classId)
+{
+  ClassList::iterator i = classList.find(classId);
+  if (i == classList.end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
+  return (*i).second;
+}
+
 
 //++
@@ -168,17 +92,9 @@
 
 //++
-// Links	Voir
+// Links	See
 // PInPersist
 // POutPersist
-// PPersistMgr
-// PShPersist
-//--
-
-PShPersist*
-PShPersist::FindObject(int_4 objId)
-{
-  DBASSERT(objList);
-  return (*objList)[objId];
-}
+// PIOPersist
+//--
   
 //++
@@ -213,8 +129,5 @@
 //--
 {
-   // On doit tout d'abord ecrire notre type
-   s << ClassId();
-   // Puis on s'ecrit, tout betement...
-   WriteSelf(s);
+   s.PutObject(this);
 }
 
@@ -226,85 +139,49 @@
 //	Relit l'objet dans le fichier ppersist. Il faut connaître a priori
 //	le type de l'objet. Pour une relecture avec création automatique du bon
-//	objet, utiliser PPersistMgr::ReadObject.
-//--
-{
-   // A n'utiliser que si on connait a priori
-   // le vrai type de l'objet.
-
-   // On doit tout d'abord lire notre type
-   int_4 classId;
-   s >> classId;
-   if (classId != ClassId()) {
-    cerr << "PPersist::Read() Object type (=" << ClassId() << ") mismatch (type in file="  
-         << classId << ")" << endl;
-    THROW(typeMismatchErr); }
-   // Puis on se lit, tout betement...
-   
-   ReadSelf(s);
-}
-
-//++
-int_4
-PPersist::Write(POutPersist& s, int_4 key) const
-//
-//	Ecrit l'objet dans le fichier PPersist avec un tag ayant "key" comme 
-//	valeur du champ clé du tag.
-//--
-{
-  int_4 rc;
-  // On ecrit le tag de positionnement et on recupere le numero de tag
-  rc = s.WriteTag(key, NULL);
-  // avant d'ecrire l'objet lui-meme
-  Write(s);
-  return(rc);
-}
-
-//++
-int_4
-PPersist::Write(POutPersist& s, int_4 key, string& nom) const
-//
-//	Ecrit l'objet dans le fichier PPersist avec un tag ayant "key", nom comme 
-//	valeurs des champs clé et nom  du tag.
-//--
-{
-  int_4 rc;
-  // On ecrit le tag de positionnement et on recupere le numero de tag
-  rc = s.WriteTag(key, nom.c_str());
-  // avant d'ecrire l'objet lui-meme
-  Write(s);
-  return(rc);
-}
-
-//++
-void
-PPersist::ReadAtTag(PInPersist& s, int_4 tagid)
+//	objet, utiliser PInPersist::ReadObject.
+//  Il faut qu'on soit un objet ecrit 
+//--
+{
+  // We should be the exact type  
+  // Check tag value
+  char ppstype;
+  s.GetRawByte(ppstype);
+  if (ppstype != PInPersist::PPS_OBJECT) {
+    throw TypeMismatchExc("PPersist::Read : not an object in flow");
+  }
+  
+  // Check class id
+  uint_8 classId;
+  s.GetRawU8(classId);
+  if (classId != PIOPersist::Hash(typeid(*this).name())) {
+    throw TypeMismatchExc("PPersist::Read : not the same object type");
+  }
+
+  ReadSelf(s);
+}
+
+//++
+void
+PPersist::Write(POutPersist& s, string const& tag) const
+//
+//	Ecrit l'objet dans le fichier PPersist avec un tag 
+//--
+{
+  s.WriteTag(tag);
+  s.PutObject(this);
+}
+
+//++
+void
+PPersist::ReadAtTag(PInPersist& s, string const& tag)
 //
 //	Lit l'objet à la position du tag numéro "tagid".
 //--
 {
-  if (s.GotoTag(tagid))  Read(s);
-  else {
-    cerr << "PInPersist::GotoTag()  Error ! \n" << 
-	    "From PPersist::ReadAtTag(PInPersist, tag= " << tagid << ") " << endl; 
-    THROW(fileErr);
-  }
-  return;    
-}
-
-//++
-void
-PPersist::ReadAtKey(PInPersist& s, int_4 key)
-//
-//	Lit l'objet à la position du tag contenant la clé "key".
-//--
-{
-  if (s.GotoKey(key))  Read(s);
-  else {
-    cerr << "PInPersist::GotoKey()  Error ! \n" << 
-	    "From PPersist::ReadAtKey(PInPersist, key= " << key << ") " << endl; 
-    THROW(fileErr);
-  }
-  return;    
-}
+  if (!s.GotoTag(tag))
+    throw NotFoundExc("PPersist::ReadAtTag  tag not found");
+  Read(s);
+}
+
 
 //++
@@ -320,76 +197,4 @@
 
 
-//++
-// Class	PShPersist
-// Lib		Outils++
-// include	ppersist.h
-//
-//	Classe de base pour des objets persistants partagés.
-//	Un tel objet ne sera écrit qu'une seule fois dans un fichier
-//	donné. Les tentatives suivantes d'écriture n'écrivent qu'une
-//	référence à la première écriture.
-//
-//	Lors de la lecture, l'objet est créé lors de la première lecture,
-//	puis l'adresse de cet objet est retournée lors des lectures suivantes.
-//--
-
-//++
-// Links	Parents
-// PPersist
-//--
-
-//++
-void
-PShPersist::Write(POutPersist& s) const
-//
-//	Ecrit l'objet dans le fichier s.
-//
-//	En fait, l'objet est physiquement écrit une seule fois.
-//--
-{
-  DBASSERT(objList);
-   // On doit tout d'abord ecrire notre type
-   
-   s << ClassId();
-
-   // On doit ensuite ecrire notre identificateur et le flag d'ecriture
-   
-   char write = (mObjectID == 0) ? 255 : 0;
-   if (mObjectID == 0) {
-     (int_4&)mObjectID = (*objList).size() ? (*((*objList).rbegin())).first+1 : 1;
-     (*objList)[mObjectID] = (PShPersist*)this; 
-   }
-
-   s << mObjectID << write ;
-   
-   // Puis, si necessaire, on s'ecrit
-   
-   if (write)
-     WriteSelf(s);
-}
-
-PShPersist::~PShPersist()  // Une securite peut-etre facultative
-{
-  DBASSERT(objList);
-  if (mObjectID) {
-    DBASSERT(!objList->size() && (objList->find(mObjectID) != objList->end()));
-    objList->erase(mObjectID);
-  }
-}
-
-void
-PPersistMgr::Reset()
-{
-  DBASSERT(PShPersist::objList);
-  for (PShPersist::ObjList::iterator i = PShPersist::objList->begin(); 
-       i != PShPersist::objList->end(); i++)
-    (*i).second->mObjectID = 0; // Une securite peut-etre facultative
-
-  PShPersist::objList->erase(PShPersist::objList->begin(), PShPersist::objList->end());
-}
-
-#define PIOP_Delim  '\n'   // Delimiteur de ligne 
-//  Les noms ne peuvent depasser 255 caracteres  
-#define MAXTAGNAMELEN  255   
 
 //++
@@ -407,215 +212,101 @@
 //--
 {
-  mSbsz = 0;     // Pour conserver les noms des tags ( V4 et au dela )
-  mSbuf = NULL;
-  mTags = NULL;
-  mNTags = 0;    //    "        "        "           "
-  fName = flnm;
-#ifdef RFIO
-  s = new erosifstream(flnm.c_str(),"rb");
+  s = new ifstream(flnm.c_str(),ios::in | IOS_BIN); 
+
+  // Read and check header
+
+  char rbuf[36];
+  GetRawBytes(rbuf, 32);
+  if (strncmp(rbuf,"PlanckDPC-PPersistFile", 22) != 0)  {
+    throw FileFormatExc("PInPersist::PInPersist  bad header");
+  }
+  version = atoi(rbuf+24);
+
+  // read endianness
+  GetRawBytes(rbuf, 32);
+  if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
+    bigEndian = true;
+  else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
+    bigEndian = false;
+  else {
+    throw FileFormatExc("PInPersist::PInPersist  bad header - endianness");
+  }
+
+  // read creation date
+  GetRawBytes(rbuf, 32);
+  rbuf[32] = '\0'; 
+  struct tm tm;
+  strptime(rbuf,"%d/%m/%Y %T GMT",&tm);
+  creationdate = mktime(&tm);
+
+  if (scan) Scan();
+}
+
+
+
+PInPersist::~PInPersist()
+{
+  delete s;
+}
+
+
+void
+PInPersist::Scan()
+{
+  // On cherche la liste des tags, a la fin du fichier
+
+  char ppstype;
+  size_t debut;
+#ifdef STREAMPOS_IS_CLASS
+  debut = s->tellg().offset();
 #else
-// $CHECK$ EA  ios::binary (ou ios::bin) doit exister PARTOUT.
-// Voir note dans defs.h pres de HAS_IOS_BIN
-#if defined(__MWERKS__)
-  s = new ifstream(flnm.c_str(),ios::in | ios::binary); // ios::binary pas connnu partout - $CHECK$ Reza 13/02/98
-#else
-  s = new ifstream(flnm.c_str(),ios::in );
+  debut = s->tellg();
 #endif
-#endif
-  PPersistMgr::Reset();
-  char rbuf[36];
-  GetBytes(rbuf, 32);
-  if (strncmp(rbuf,"PEIDA-PPersistFile", 18) != 0)  {
-    cerr << "PInPersist::PInPersist Error : File " << flnm << " (empty file or bad header)" 
-         << endl;
-    THROW(fileErr); }
-  version = atoi(rbuf+20);
-  bigEndian = IS_BIG_ENDIAN; // Les V2 sont relus en mode natif
-  if (version >= 3) {
-    GetBytes(rbuf, 32);
-    if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
-      bigEndian = true;
-    else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
-      bigEndian = false;
-    else {
-      cerr << "PInPersist::PInPersist Error : File" << flnm;
-      cerr << " (V>=3 et ni BIG-ENDIAN, ni LITTLE-ENDIAN" << endl;
-      THROW(fileErr);
-    }
-  }
-  if (version >= 5) {   // On lit la date de creation (V5 et au-dela)
-    GetBytes(rbuf, 32);
-    rbuf[32] = '\0'; 
-    for(int k=0; k<32; k++) 
-      if (rbuf[k] == ' ') { rbuf[k] = '\0';  break; }
-    creationdate = rbuf;
-    }  // Fin de lecture de date
-  else creationdate = "??/??/??" ;
-  // Le fichier peut contenir des tag  (V4 et au dela)
-  if ( (version >= 4) && scan )  Scan();
-}
-
-
-
-PInPersist::~PInPersist()
-{
-  list<char*>::iterator it;
-  for(it = mSbuffs.begin(); it != mSbuffs.end(); it++)  delete[] (*it);
-  if (mTags)  delete[] mTags;
-  delete s;
-  PPersistMgr::Reset();
-}
-
-// A cause de aCC qui ne veut pas char* b = ""
-static char ChaineVide[2] = {'\0', '\0'};
-
-void
-PInPersist::Scan()
-{
-// On parcourt le fichier depuis la fin pour identifier tous les tags
-  int_8 debut, prev, premier;
-  int_4 ntag, ntc, ll;
-  uint_2 ln;
-  char pad[4];
-
-  #if defined(STREAMPOS_IS_CLASS) && !defined(RFIO)
-  debut = s->tellg().offset();
-  #else
-  debut = s->tellg();
-  #endif
-
-  premier = 0;
-  s->seekg(-(sizeof(int_8)+sizeof(int_4)), ios::end);
-  GetI8(prev);
-  GetI4(ntag);
-  if ( (ntag <= 0) || (prev < 0) )  
-    { s->seekg(debut,ios::beg); return; }
-
-  mNTags = ntag;
-  mTags = new PPFTag[ntag];
-
-  PPFTag* tag;
-  while( (prev > 0)  && (ntag > 0) ) {
-    s->seekg(prev);
-    if (ntag == 1)   premier = prev;
-    GetI8(prev);
-    GetI4(ntc);
-    ntag--;
-    if (ntc != ntag) {
-      cerr << "PInPersist::Scan() / Error: NTag,TC= " << ntag << "," << ntc << endl;
-      THROW(fileErr);
-    }
-    tag = mTags+ntag;
-    GetI4(tag->key);
-    GetU2(ln);  
-    if (ln > 0) {
-      tag->lnom = ln;
-      tag->nom = GetCStr(ln);
-      GetBytes(tag->nom, ln+1); 
-      ll = 3-((ln+2)%4);
-      GetBytes(pad, ll);
-    }
-    else { 
-      GetU2(ln);
-      tag->lnom = 0;
-      tag->nom = ChaineVide;
-    }
-// On recupere la position pour l'objet qui suit
-  #ifdef STREAMPOS_IS_CLASS
-  tag->popos = s->tellg().offset();
-  #else
-  tag->popos = s->tellg();
-  #endif
-
-  GetI4(tag->cid); 
-  }
-
-  if ( (ntag != 0) || (prev >= 0) ) {  // En principe , ca ne doit pas arriver
-    cerr << "PInPersist::Scan() / Error: (End: ntag=" << ntag <<
-            " prev=" << (int_4)prev << endl;
-    THROW(fileErr);
-  }
-// on se repositionne au debut du 1er objet du fichier 
-  if (premier == debut)  GotoTag(0); 
-  else s->seekg(debut);
-  return;
-}
-
-char*
-PInPersist::GetCStr(uint_2 sz)
-{
-char* rs;
-sz += 1;  // Pour le 0 de la fin
-if (sz > mSbsz)
-  { mSbsz = (sz > (MAXTAGNAMELEN+1)) ? sz : (MAXTAGNAMELEN+1);
-  mSbuf = new char[mSbsz];  mSbuffs.push_back(mSbuf); }
-
-rs = mSbuf;
-mSbuf += sz;
-mSbsz -= sz;
-return(rs);
-}
+
+  // Find tag entries at end of file
+  s->seekg(-(sizeof(int_8)+1), ios::end);
+  GetRawByte(ppstype);
+  if (ppstype != PPS_EOF)
+    throw FileFormatExc("PInPersist::Scan   corrupted file, no eof entry at end of file");
+
+  int_8 pos;
+  GetRawI8(pos);
+  if (pos < 0) {  // no tags
+    s->seekg(debut);
+    return;
+  }
+
+  char buffer[MAXTAGLEN+1];
+  s->seekg(pos);
+  while (true) {
+    GetRawByte(ppstype);
+    if (ppstype == PPS_EOF) break;
+    
+    if (ppstype != PPS_TAG)
+      throw FileFormatExc("PInPersist::Scan   corrupted file, bad tag entry");
+
+    GetRawI8(pos);
+    int_4 len;
+    GetRawI4(len);
+    if (len > MAXTAGLEN) 
+      throw FileFormatExc("PInPersist::Scan   corrupted file, tag name too long");
+    GetRawBytes(buffer, len);
+    buffer[len] = '\0';
+
+    tags[buffer] = pos;
+  }
+  s->seekg(debut);
+}
+
 
 bool 
-PInPersist::GotoTag(int_4 num)
-{
-  if ( (num < 0) || (num >= mNTags) )  return(false);
-  s->seekg(mTags[num].popos);
+PInPersist::GotoTag(string const& name)
+{
+  map<string, int_8>::iterator i = tags.find(name);
+  if (i == tags.end()) 
+    return false;
+      //    throw NotFoundExc("PInPersist::GotoTag   tag not found");
+  s->seekg((*i).second);
   return(true); 
-}
-
-bool 
-PInPersist::GotoKey(int_4 key, int rang)
-{
-  if (rang < 0)  return(false);
-  int n = 0, i; 
-  int fnd = -1;
-  for(i=0; i<mNTags; i++) 
-    if (mTags[i].key == key) { 
-      if (n == rang) { fnd = i;   break; }
-      n++; }
-    
-  if (fnd >= 0) return(GotoTag(fnd));
-  else return(false);
-}
-
-int 
-PInPersist::NbKey(int_4 key)
-{
-  int n = 0, i;
-  for(i=0; i<mNTags; i++) 
-    if (mTags[i].key == key)  n++;
-  return(n);
-}
-
-void
-PInPersist::ListTags()
-{
-  cout << "PInPersist/ File " << fName << "\n";
-  cout << "Nb Tags in file : " << mNTags << "\n";
-  string str;
-  int i;
-  for(i=0; i<mNTags; i++) {
-    str = mTags[i].nom;
-    cout << i << "- CId= " << mTags[i].cid << " Key= " 
-         << mTags[i].key << " ( " << str << " )\n" ;
-  }
-  cout << endl;
-  return;  
-}
-
-int_4
-PInPersist::TagKey(int_4 num, int_4& cid, int_4& ln)
-{
-  if ( (num < 0) || (num >= mNTags) )  return(0);
-  cid = mTags[num].cid; ln = mTags[num].lnom; 
-  return(mTags[num].key);
-}
-
-string
-PInPersist::TagName(int_4 num)
-{
-  if ( (num < 0) || (num >= mNTags) )  return("");
-  return((string)mTags[num].nom);
 }
 
@@ -645,15 +336,4 @@
 //--
 
-void
-PInPersist::GetByte(char& c)
-{
-  GetBytes(&c, 1);
-}
-
-void
-PInPersist::GetBytes(void* ptr, size_t bytes)
-{
-  s->read((char*)ptr, bytes);
-}
 
 static inline void bswap8(void* p)
@@ -686,8 +366,102 @@
 }
 
+
+void
+PInPersist::GetRawByte(char& c)
+{
+  GetRawBytes(&c, 1);
+}
+
+void
+PInPersist::GetRawBytes(void* ptr, size_t bytes)
+{
+  s->read((char*)ptr, bytes);
+}
+
+void
+PInPersist::GetRawI2   (int_2& result)
+{
+  GetRawBytes(&result, sizeof(int_2));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&result);
+}
+
+void
+PInPersist::GetRawI4   (int_4& result)
+{
+  GetRawBytes(&result, sizeof(int_4));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&result);
+}
+
+void
+PInPersist::GetRawI8   (int_8& result)
+{
+  GetRawBytes(&result, sizeof(int_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::GetRawU8   (uint_8& result)
+{
+  GetRawBytes(&result, sizeof(uint_8));
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&result);
+}
+
+void
+PInPersist::CheckTag(short datasz)
+{
+  char ppstype;
+  GetRawByte(ppstype);
+  if (ppstype != PPS_SIMPLE + datasz)
+    throw TypeMismatchExc("PInPersist::CheckTag   bad type in ppersist file");
+}
+
+void
+PInPersist::CheckArrayTag(short datasz, size_t sz)
+{
+  char ppstype;
+  GetRawByte(ppstype);
+  size_t filesz;
+  if (sz <= 0x7fff) {
+    if (ppstype != PPS_SIMPLE_ARRAY + datasz)
+      throw TypeMismatchExc("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 TypeMismatchExc("PInPersist::CheckTag   bad type in ppersist file");
+    int_4 ff;
+    GetRawI4(ff); filesz=ff;
+  } else {
+    if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
+      throw TypeMismatchExc("PInPersist::CheckTag   bad type in ppersist file");
+    uint_8 ff;
+    GetRawU8(ff); filesz=ff;
+  }
+  if (filesz != sz)
+    throw TypeMismatchExc("PInPersist::CheckTag   bad array size in ppersist file");
+}
+
+void
+PInPersist::GetByte(char& c)
+{
+  CheckTag(1);
+  GetRawBytes(&c, 1);
+}
+
+void
+PInPersist::GetBytes(void* ptr, size_t bytes)
+{
+  CheckArrayTag(1, bytes);
+  GetRawBytes(ptr, bytes);
+}
 void
 PInPersist::GetR4   (r_4& result)
 {
-  GetBytes(&result, sizeof(r_4));
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(r_4));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&result);
@@ -698,5 +472,6 @@
 PInPersist::GetR4s  (r_4* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(r_4));
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(r_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -710,5 +485,6 @@
 PInPersist::GetR8   (r_8& result)
 {
-  GetBytes(&result, sizeof(r_8));
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(r_8));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&result);
@@ -718,5 +494,6 @@
 PInPersist::GetR8s  (r_8* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(r_8));
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(r_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -730,5 +507,6 @@
 PInPersist::GetI2   (int_2& result)
 {
-  GetBytes(&result, sizeof(int_2));
+  CheckTag(2);
+  GetRawBytes(&result, sizeof(int_2));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap2(&result);
@@ -738,5 +516,6 @@
 PInPersist::GetI2s  (int_2* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(int_2));
+  CheckArrayTag(2,n);
+  GetRawBytes(tab, n*sizeof(int_2));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -750,5 +529,6 @@
 PInPersist::GetU2   (uint_2& result)
 {
-  GetBytes(&result, sizeof(uint_2));
+  CheckTag(2);
+  GetRawBytes(&result, sizeof(uint_2));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap2(&result);
@@ -758,5 +538,6 @@
 PInPersist::GetU2s  (uint_2* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(uint_2));
+  CheckArrayTag(2,n);
+  GetRawBytes(tab, n*sizeof(uint_2));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -770,5 +551,6 @@
 PInPersist::GetI4   (int_4& result)
 {
-  GetBytes(&result, sizeof(int_4));
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(int_4));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&result);
@@ -778,5 +560,6 @@
 PInPersist::GetI4s  (int_4* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(int_4));
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(int_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -790,5 +573,6 @@
 PInPersist::GetU4   (uint_4& result)
 {
-  GetBytes(&result, sizeof(uint_4));
+  CheckTag(4);
+  GetRawBytes(&result, sizeof(uint_4));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&result);
@@ -798,5 +582,6 @@
 PInPersist::GetU4s  (uint_4* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(uint_4));
+  CheckArrayTag(4,n);
+  GetRawBytes(tab, n*sizeof(uint_4));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -811,5 +596,6 @@
 PInPersist::GetI8   (int_8& result)
 {
-  GetBytes(&result, sizeof(int_8));
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(int_8));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&result);
@@ -819,5 +605,6 @@
 PInPersist::GetI8s  (int_8* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(int_8));
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(int_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -831,5 +618,6 @@
 PInPersist::GetU8   (uint_8& result)
 {
-  GetBytes(&result, sizeof(uint_8));
+  CheckTag(8);
+  GetRawBytes(&result, sizeof(uint_8));
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&result);
@@ -839,5 +627,6 @@
 PInPersist::GetU8s  (uint_8* tab, size_t n)
 {
-  GetBytes(tab, n*sizeof(uint_8));
+  CheckArrayTag(8,n);
+  GetRawBytes(tab, n*sizeof(uint_8));
   if (bigEndian == IS_BIG_ENDIAN) return;
 
@@ -852,7 +641,72 @@
 PInPersist::GetLine(char* ptr, size_t len)
 {
-  s->getline(ptr, len, PIOP_Delim);
-}
-
+  char ppstype;
+  GetRawByte(ppstype);
+  if (ppstype != PPS_LINE) 
+    throw TypeMismatchExc("PInPersist::GetLine   bad type in ppersist file");
+  s->getline(ptr, len, '\n');
+}
+
+void
+PInPersist::GetStr(string& str)
+{
+  char ppstype;
+  GetRawByte(ppstype);
+  if (ppstype != PPS_STRING) 
+    throw TypeMismatchExc("PInPersist::GetLine   bad type in ppersist file");
+  int_2 len;
+  GetRawI2(len);
+  char * buff = new char(len+1);
+  GetRawBytes(buff, len);
+  buff[len] = '\0';
+  str = buff;
+  delete[] buff;
+}
+
+PPersist*
+PInPersist::ReadObject()
+{
+  // Get tag
+  char ppstype;
+  GetRawByte(ppstype);
+  if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
+    throw TypeMismatchExc("PInPersist::ReadObject : not an object in flow");
+  }
+
+  if (ppstype == PPS_NULL) {
+    return NULL;
+  } else if (ppstype == PPS_OBJECT) {
+    // Get class id
+    uint_8 classId;
+    GetRawU8(classId);
+    
+    // Get factory method
+    ClassCreatorFunc f = FindCreatorFunc(classId);
+    if (!f) {
+      throw NotFoundExc("PInPersist::ReadObject   class not registered");
+    }
+    
+    // Create object
+    PPersist* object = f();
+    object->ReadSelf(*this);
+    assignObjectId(object);
+    return object;
+  } else {
+    // Get object id
+    int_4 id;
+    GetRawI4(id);
+    if (id <0 || id>=objList.size()) {
+      throw FileFormatExc("PInPersist::ReadObject    invalid object id for reference");
+    }
+    return objList[id];
+  }
+}
+
+int_4 
+PInPersist::assignObjectId(PPersist* x)
+{
+  objList.push_back(x);
+  return objList.size()-1;
+}
 
 //++
@@ -880,81 +734,69 @@
     bigEndian = endianness;
 
-#ifdef RFIO
-  s = new erosofstream(flnm.c_str(),"wb");
+  // Output stream creation
+  s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);  
+
+  // Header
+  PutRawBytes("PlanckDPC-PPersistFile V1                ",32);
+  PutRawBytes(bigEndian 
+	   ? "BIG-ENDIAN                             "
+	   : "LITTLE-ENDIAN                          ",32);
+
+// ---- GMT creation date of the file
+  time_t tm = time(NULL);
+  char datestring[33];
+  int l=strftime(datestring,32,"%d/%m/%Y %T GMT",gmtime(&tm));
+  for(int i=l; i<32; i++)  datestring[i] = ' ';
+  datestring[32] = '\0'; 
+  PutRawBytes(datestring, 32);
+}
+
+POutPersist::~POutPersist()
+{
+  if (tags.size() == 0) {
+    PutRawByte(PPS_EOF);
+    PutRawI8(-1);
+  } else {
+    int_8 tagPos;
+#ifdef STREAMPOS_IS_CLASS
+    tagPos = s->tellp().offset();
 #else
-#if defined(__MWERKS__)
-  s = new ofstream(flnm.c_str(),ios::out | ios::binary);   // ios::binary pas connnu partout - $CHECK$ Reza 13/02/98
-#else
-  s = new ofstream(flnm.c_str(),ios::out );
+    tagPos = s->tellp();
 #endif
-#endif
-  PPersistMgr::Reset();
-  PutBytes("PEIDA-PPersistFile V5           ",32);
-  PutBytes(bigEndian 
-	   ? "BIG-ENDIAN                      "
-	   : "LITTLE-ENDIAN                   ",32);
-// ---- On ecrit la date de creation a partir de V5 
-  Date today;
-  string stod = today.DateStr(Date::kLocalTime) + "#" + today.TimeStr(Date::kLocalTime);
-  char buff[36];
-  int l = stod.length();
-  if (l < 33) strcpy(buff, stod.c_str()); 
-  else strncpy(buff, stod.c_str(), 33);
-  for(int i=l+1; i<32; i++)  buff[i] = ' ';
-  buff[32] = '\0'; 
-  PutBytes(buff, 32);
-//  Fin d'ecriture de date --------
-  previous = -1;  // Pas de Tag precedant
-  numTag = 0;
-}
-
-POutPersist::~POutPersist()
-{
-  PutI8(previous);
-  PutI4(numTag);
-  delete s;
-  PPersistMgr::Reset();
-}
-
-
-int_4 
-POutPersist::WriteTag(int_4 key, char const * nom)
-{
-  int_8 nexprev;
-  uint_2 l;
-  int ll;
-  char pad[4] = {'\0', '\0', '\0', '\0'};
+    for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
+      string name = (*i).first;
+      int_8 pos = (*i).second;
+      PutRawByte(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);
+    PutRawI8(tagPos);
+  }
+
+  delete s;   // Close the stream
+}
+
+
+void
+POutPersist::WriteTag(string const& name)
+{
+  if (name.length() > MAXTAGLEN) 
+    throw ParmError("POutPersist::WriteTag   tag name too long");
+
+  if (tags.find(name) != tags.end())
+    throw DuplicateIdExc("POutPersist::WriteTag   duplicate tag name");
+
+  // Get current file position
+  int_8 tagPos;
 
   #ifdef STREAMPOS_IS_CLASS
-  nexprev = s->tellp().offset();
+  tagPos = s->tellp().offset();
   #else
-  nexprev = s->tellp();
+  tagPos = s->tellp();
   #endif
-// On ecrit dans l'ordre 
-//  - La position du tag precedant (-1 s'il n'y en a pas)
-//  - Le numero de tag ( qui s incremete automatiquement )
-//  - La cle utilisateur  (key)
-//  - La longueur du nom 
-//  - le nom lui-meme    (Avec un pad afin de faire nom+longueur=multiple de 4)
-  PutI8(previous);
-  PutI4(numTag);
-  PutI4(key);
-  if (nom==NULL)   { 
-    PutU2(0);  PutU2(0);
-  }  
-  else {
-    ll = strlen(nom);
-    if (ll <= 0) {
-      PutU2(0);  PutU2(0);
-    } 
-    l = (ll <=  MAXTAGNAMELEN) ? ll : MAXTAGNAMELEN ; 
-    PutU2(l);
-    PutBytes(nom,l+1); 
-    ll = 3-((ll+2)%4);
-    PutBytes(pad, ll);
-  }
-  previous = nexprev;
-  numTag++;
-  return((numTag-1));
+
+  tags[name] = tagPos;
 }
 
@@ -978,4 +820,5 @@
 // void POutPersist::PutU8   (uint_8 result)
 // void POutPersist::PutU8s  (uint_8 const* tab, size_t n)
+// void POutPersist::PutStr  (string const&)
 //	Ecriture de données portables.. Pour chaque type
 //	de données, on peut écrire une valeur, ou un tableau de valeurs.
@@ -988,13 +831,80 @@
 
 void
+POutPersist::PutRawBytes(void const* ptr, size_t bytes)
+{
+  s->write((char const*)ptr, bytes);
+}
+
+void
+POutPersist::PutRawByte(char c)
+{
+  PutRawBytes(&c, 1);
+}
+
+void
+POutPersist::PutRawI2   (int_2 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap2(&val);
+
+  PutRawBytes(&val, sizeof(int_2));
+}
+
+void
+POutPersist::PutRawI4   (int_4 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap4(&val);
+
+  PutRawBytes(&val, sizeof(int_4));
+}
+
+void
+POutPersist::PutRawI8   (int_8 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(int_8));
+}
+
+void
+POutPersist::PutRawU8   (uint_8 val)
+{
+  if (bigEndian != IS_BIG_ENDIAN)
+    bswap8(&val);
+
+  PutRawBytes(&val, sizeof(uint_8));
+}
+
+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);
+    PutRawI4(sz);
+  } else {
+    PutRawByte(PPS_SIMPLE_ARRAY8 + datasz);
+    PutRawU8(sz);
+  } 
+}
+
+void
 POutPersist::PutByte(char c)
 {
-  PutBytes(&c, 1);
-}
+  PutRawByte(PPS_SIMPLE + 1);
+  PutRawBytes(&c, 1);
+}
+
+
 
 void
 POutPersist::PutBytes(void const* ptr, size_t bytes)
 {
-  s->write((char const*)ptr, bytes);
+  PutArrayTag(1, bytes);
+  PutRawBytes(ptr, bytes);
 }
 
@@ -1002,8 +912,10 @@
 POutPersist::PutR4   (r_4 val)
 {
+  PutRawByte(PPS_SIMPLE + 4);
+  
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&val);
 
-  PutBytes(&val, sizeof(r_4));
+  PutRawBytes(&val, sizeof(r_4));
 }
 
@@ -1011,9 +923,15 @@
 POutPersist::PutR4s  (r_4 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(r_4));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutR4(tab[i]);
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(r_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      r_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(r_4));
+    }
+  }
 }
 
@@ -1021,8 +939,10 @@
 POutPersist::PutR8   (r_8 val)
 {
+  PutRawByte(PPS_SIMPLE + 8);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&val);
 
-  PutBytes(&val, sizeof(r_8));
+  PutRawBytes(&val, sizeof(r_8));
 }
 
@@ -1030,9 +950,15 @@
 POutPersist::PutR8s  (r_8 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(r_8));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutR8(tab[i]);
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(r_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      r_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(r_8));
+    }
+  }
 }
 
@@ -1040,8 +966,10 @@
 POutPersist::PutI2   (int_2 val)
 {
+  PutRawByte(PPS_SIMPLE + 2);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap2(&val);
 
-  PutBytes(&val, sizeof(int_2));
+  PutRawBytes(&val, sizeof(int_2));
 }
 
@@ -1049,9 +977,15 @@
 POutPersist::PutI2s  (int_2 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(int_2));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutI2(tab[i]);
+  PutArrayTag(2, n);
+  
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_2));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_2 val = tab[i];
+      bswap2(&val);
+      PutRawBytes(&val, sizeof(int_2));
+    }
+  }
 }
 
@@ -1059,8 +993,10 @@
 POutPersist::PutU2   (uint_2 val)
 {
+  PutRawByte(PPS_SIMPLE + 2);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap2(&val);
 
-  PutBytes(&val, sizeof(uint_2));
+  PutRawBytes(&val, sizeof(uint_2));
 }
 
@@ -1068,9 +1004,15 @@
 POutPersist::PutU2s  (uint_2 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(uint_2));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutU2(tab[i]);
+  PutArrayTag(2, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_2));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_2 val = tab[i];
+      bswap2(&val);
+      PutRawBytes(&val, sizeof(uint_2));
+    }
+  }
 }
 
@@ -1078,8 +1020,10 @@
 POutPersist::PutI4   (int_4 val)
 {
+  PutRawByte(PPS_SIMPLE + 4);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&val);
 
-  PutBytes(&val, sizeof(int_4));
+  PutRawBytes(&val, sizeof(int_4));
 }
 
@@ -1087,9 +1031,15 @@
 POutPersist::PutI4s  (int_4 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(int_4));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutI4(tab[i]);
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(int_4));
+    }
+  }
 }
 
@@ -1097,8 +1047,10 @@
 POutPersist::PutU4   (uint_4 val)
 {
+  PutRawByte(PPS_SIMPLE + 4);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap4(&val);
 
-  PutBytes(&val, sizeof(uint_4));
+  PutRawBytes(&val, sizeof(uint_4));
 }
 
@@ -1106,9 +1058,15 @@
 POutPersist::PutU4s  (uint_4 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(uint_4));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutU4(tab[i]);
+  PutArrayTag(4, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_4));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_4 val = tab[i];
+      bswap4(&val);
+      PutRawBytes(&val, sizeof(uint_4));
+    }
+  }
 }
 
@@ -1116,8 +1074,10 @@
 POutPersist::PutI8   (int_8 val)
 {
+  PutRawByte(PPS_SIMPLE + 8);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&val);
 
-  PutBytes(&val, sizeof(int_8));
+  PutRawBytes(&val, sizeof(int_8));
 }
 
@@ -1125,9 +1085,15 @@
 POutPersist::PutI8s  (int_8 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(int_8));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutI8(tab[i]);
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(int_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      int_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(int_8));
+    }
+  }
 }
 
@@ -1135,8 +1101,10 @@
 POutPersist::PutU8   (uint_8 val)
 {
+  PutRawByte(PPS_SIMPLE + 8);
+
   if (bigEndian != IS_BIG_ENDIAN)
     bswap8(&val);
 
-  PutBytes(&val, sizeof(uint_8));
+  PutRawBytes(&val, sizeof(uint_8));
 }
 
@@ -1144,9 +1112,23 @@
 POutPersist::PutU8s  (uint_8 const* tab, size_t n)
 {
-  if (bigEndian == IS_BIG_ENDIAN)
-    PutBytes(tab, n*sizeof(uint_8));
-  else
-    for (unsigned int i=0; i<n; i++)
-      PutU8(tab[i]);
+  PutArrayTag(8, n);
+
+  if (bigEndian == IS_BIG_ENDIAN) {
+    PutRawBytes(tab, n*sizeof(uint_8));
+  } else {
+    for (unsigned int i=0; i<n; i++) {
+      uint_8 val = tab[i];
+      bswap8(&val);
+      PutRawBytes(&val, sizeof(uint_8));
+    }
+  }
+}
+
+void
+POutPersist::PutStr(string const& str) 
+{
+  PutRawByte(PPS_STRING);
+  PutRawI2(str.length());
+  PutRawBytes(str.c_str(), str.length());
 }
 
@@ -1154,67 +1136,55 @@
 POutPersist::PutLine(char const* ptr, size_t len)
 {
+  PutRawByte(PPS_LINE);
+
   if (len == 0)  len = strlen(ptr);
-  s->write(ptr, len);
-#ifdef RFIO
-  char cd = PIOP_Delim;
-  s->write(&cd, 1);
-#else
-  s->put(PIOP_Delim);
-#endif  
+  PutRawBytes(ptr, len);
+  PutRawByte('\n');
+}
+
+void
+POutPersist::PutObject(PPersist const* obj) 
+{
+  if (serializeNullAndRepeat(obj)) return;
+
+  PutRawByte(PPS_OBJECT);
+  PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
+  assignObjectId(obj);
+  obj->WriteSelf(*this);
+}
+
+bool
+POutPersist::serializeNullAndRepeat(PPersist const* x)
+{
+  if (x == NULL) {
+    PutRawByte(PPS_NULL);
+    return true;
+  }
+
+  int_4 id = findObjectId(x);
+  if (id >= 0) {
+    PutRawByte(PPS_REFERENCE);
+    PutRawI4(id);
+    return true;
+  }
   
-}
-
-
-// ---  Classe d'initialisation de PEIDA++, (PPersistMgr en particulier)
-int PeidaInitiator::FgInit = 0;
-
-PeidaInitiator::PeidaInitiator()
-{
-  FgInit++;
-  if (FgInit > 1)  return;
-
-  InitFailNewHandler();
-
-  #ifdef xx__mac__
-  //InitToolBox();
-  //SIOUXSettings.initializeTB = FALSE;
-  SIOUXSettings.autocloseonquit = FALSE;
-  SIOUXSettings.asktosaveonclose = FALSE;
-  SIOUXSettings.showstatusline = TRUE;
-  #endif
-
-  PPersistMgr::classList = new PPersistMgr::ClassList;
-  PShPersist::objList    = new PShPersist::ObjList;
-  
-
-#if (!defined(__GNUG__) && !defined(__MWERKS__) && !defined(HPUX))
-  // pas de bufferisation pour printf   cmv 18/3/97 selon E.A.
-  // setvbuf(stdout,NULL,_IOLBF,0); setvbuf(stderr,NULL,_IOLBF,0);
-  setlinebuf(stdout);
-  setlinebuf(stderr);
-#endif
-
-  // si var env PEIDA_NOPRTVER definie pas de print
-  if(!getenv("PEIDA_NOPRTVER")) PrintPeidaVersion();
-}
-
-PeidaInitiator::~PeidaInitiator()
-{
-  FgInit--;
-  if (FgInit == 0)
-    {
-    delete PPersistMgr::classList; PPersistMgr::classList = NULL;
-    delete PShPersist::objList;    PShPersist::objList = NULL;
-    }
-}
-
-double PeidaInitiator::Version(bool fgprt)
-{
-if (fgprt)  PrintPeidaVersion();
-return(PeidaVersion());
-}
- 
-// On met un objet initiator en statique, pour les loaders qui savent 
-// appeler le constructeur des objets statiques   Reza 08/98
-static PeidaInitiator ppeidainit;
-
+  return false;
+}
+
+int_4 
+POutPersist::assignObjectId(PPersist const* x)
+{
+  int_4 id = objList.size();
+  objList[x] = id;
+  return id;
+}
+
+int_4 
+POutPersist::findObjectId(PPersist const* x)
+{
+  ObjList::iterator i = objList.find(x);
+  if (i == objList.end()) return -1;
+  return (*i).second;
+}
+
+
