source: Sophya/trunk/SophyaLib/BaseTools/ppersist.cc@ 4085

Last change on this file since 4085 was 4051, checked in by ansari, 14 years ago

modifs ds PPersist (classe PIOPersist) pour permettre l'enregistrement automatique (1ere lecture ou ecriture) de PPFWrapperSTLVector<T> (gestionnaire ppersist de std::vector<T> , Reza+cmv 25/02/2012

File size: 21.8 KB
RevLine 
[2615]1#include "sopnamsp.h"
[241]2#include "machdefs.h"
[251]3#include <stdio.h>
4#include <sys/types.h>
5#include <time.h>
[241]6#include "pexceptions.h"
[219]7#include "ppersist.h"
[802]8#include "anydataobj.h"
[2322]9#include <iostream>
[2657]10#include <iomanip>
[241]11#include <typeinfo>
[219]12
[2475]13// ------------------------- Historique ---------------------------
14// Le code de ppersist a ete separe en deux en Decembre 2003
15// a partir de la version CVS (1.26 - ppersist.cc) et
16// (1.19 - ppersist.h) .
17// la partie sur l'ecriture des donnees de base et leurs tableaux
18// a ete mis dans les fichiers ppfbinstream.h .cc
19// (Classes PPFBinaryInputStream et PPFBinaryOutputStream
20// -----------------------------------------------------------------
[219]21
22
[241]23
[2805]24/*!
25 \class SOPHYA::PIOPersist
26 \ingroup BaseTools
27 Handles (statically) the registration of PPF Sophya Persistence) handler classes.
28 \sa PPersist
29*/
30
31
[219]32//++
[241]33// Class PIOPersist
[219]34// Lib Outils++
35// include ppersist.h
36//
[241]37// Root class for persistant files. Handles the registration of
38// persistant classes
[219]39//--
40
[742]41MD5_CONTEXT PIOPersist::ctx;
[802]42PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
43map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
44map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
[241]45
[269]46//++
47void
48PIOPersist::Initialize()
49// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
50//--
51{
[802]52ppclassList = new PIOPersist::ClassList;
53ppclassNameList = new map<string, uint_8>;
54dobjclassNameList = new map<string, uint_8>;
[1900]55cout << " PIOPersist::Initialize() Starting Sophya Persistence management service " << endl;
[269]56}
[241]57
[2805]58/*!
59 Register a new persistence handler (PPersist) class.
60 The classId is usually a hash of the class< name, and
61 ppclass_name is typeid(PPersistClass).name() .
62 This method is called only through the PPersistRegistrar template
63*/
[219]64void
[802]65PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
[219]66{
[802]67 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
68 cerr << "RegisterClass : Error, " << hex << classId << dec
69 << " already registered." << endl;
[816]70 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
[802]71 }
72 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
73 cerr << "RegisterClass : Error (2) " << ppclass_name
74 << " already registered." << endl;
[816]75 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
[219]76 }
77
[802]78 (*ppclassList)[classId] = f;
79 (*ppclassNameList)[ppclass_name] = classId;
[219]80}
81
[2805]82/*!
83 Register a new DataObj class corresponding to a PPersist classId
84 class_typename should be typeid(DataObject).name()
85*/
[802]86void
87PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
88{
[816]89 if (ppclassList->find(classId) == ppclassList->end() ) {
90 cerr << "PIOPersist::RegisterDataObjClass() Error (1) "
91 << hex << classId << dec << " Not Found !" << endl;
92 throw( NotFoundExc("PIOPersist::RegisterDataObjClass() Not found classId ") );
93 }
94 if (dobjclassNameList->size() && (dobjclassNameList->find(class_name) != dobjclassNameList->end())) {
95 cerr << "PIOPersist::RegisterDataObjClass() Error (2)" << class_name
96 << " already registered." << endl;
97 throw(DuplicateIdExc("PIOPersist::RegisterDataObjClass() - Already registered"));
98 }
[219]99
[802]100 (*dobjclassNameList)[class_name] = classId;
101}
102
103// class_typename should be typeid(DataObject).name(), to be
104// used by POutPersist::PutDataObject() methods.
105
[2657]106//! Lists the registered PPersist handler classes and the corresponding class id.
107void
108PIOPersist::ListPPHandlers()
109{
110 cout << " PIOPersist::ListPPHandlers() - List of registered PPersist handler classes " << endl;
111 map<string, uint_8>::iterator it;
112 int k = 0;
113 for (it = (*ppclassNameList).begin(); it != (*ppclassNameList).end(); it++) {
114 cout << ++k << ": " << (*it).first << "\n" << " ClassId: Hex= "
115 << hex << (*it).second << " (Dec= " << dec << (*it).second << ")" << endl;
116 }
117}
118
119//! Lists the registered DataObj classes with the corresponding PPHandler name
120void
121PIOPersist::ListDataObjClasses()
122{
123 cout << " PIOPersist::ListDataObjClasses() : Registered DataObj class list " << endl;
124 map<string, uint_8>::iterator it;
125 int k = 0;
126 for (it = (*dobjclassNameList).begin(); it != (*dobjclassNameList).end(); it++) {
127 cout << ++k << "- " << (*it).first << " -> " << getPPClassName((*it).second) << endl;
128 }
129}
130
[2805]131//! Returns the PPersist class creator function for the specified classId
[241]132PIOPersist::ClassCreatorFunc
133PIOPersist::FindCreatorFunc(uint_8 classId)
[219]134{
[802]135 ClassList::iterator i = ppclassList->find(classId);
136 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
[241]137 return (*i).second;
[219]138}
139
[2805]140//! Returns the PPersist class name for the specified classId
[802]141string
142PIOPersist::getPPClassName(uint_8 classId)
143{
144 map<string, uint_8>::iterator i;
145 for (i= ppclassNameList->begin(); i != ppclassNameList->end(); i++)
146 if ( (*i).second == classId ) return (*i).first;
[219]147
[802]148 throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
149}
150
[2805]151//! Returns the classId for the specified PPersist class type name
[802]152uint_8
153PIOPersist::getPPClassId(string const & typ_name)
154{
155 map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
156 if (i == ppclassNameList->end())
157 throw(NotFoundExc("PIOPersist::getPPClassId() Not found className"));
158 return (*i).second;
159}
160
[2805]161//! Returns the classId for the specified PPersist class
[802]162uint_8
163PIOPersist::getPPClassId(PPersist const & ppo)
164{
165 string typ_name = typeid(ppo).name() ;
166 return (getPPClassId(typ_name) );
167}
168
[4051]169//! Return true if the specified PPersist class is found in the registered class list
170bool
171PIOPersist::checkPPClassId(PPersist const & ppo)
172{
173 string typ_name = typeid(ppo).name() ;
174 map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
175 if (i == ppclassNameList->end()) return false;
176 return true;
177}
[802]178
[2805]179//! Returns the PPersist class name for the specified classId
[802]180string
181PIOPersist::getDataObjClassName(uint_8 classId)
182{
183 map<string, uint_8>::iterator i;
184 for (i= dobjclassNameList->begin(); i != dobjclassNameList->end(); i++)
185 if ( (*i).second == classId ) return (*i).first;
186
187 throw(NotFoundExc("PIOPersist::getDataObjClassName() Not found classId"));
188}
189
[2805]190//! Returns the classId for the specified PPersist class type name
[802]191uint_8
192PIOPersist::getDataObjClassId(string const & typ_name)
193{
194 map<string, uint_8>::iterator i = dobjclassNameList->find(typ_name);
195 if (i == dobjclassNameList->end())
196 throw(NotFoundExc("PIOPersist::getDataObjClassId() Not found className"));
197 return (*i).second;
198}
199
[2805]200//! Returns the classId for the specified PPersist class
[802]201uint_8
202PIOPersist::getDataObjClassId(AnyDataObj const & o)
203{
204 string typ_name = typeid(o).name() ;
205 return (getDataObjClassId(typ_name) );
206}
207
[2805]208//! \cond
[2476]209static inline void bswap8_hash(void* p)
210{
211 uint_8 tmp = *(uint_8*)p;
212 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
213 ((tmp >> (5*8)) & 0x0000FF00) |
214 ((tmp >> (3*8)) & 0x00FF0000) |
215 ((tmp >> (1*8)) & 0xFF000000) |
216 ((tmp & 0xFF000000) << (1*8)) |
217 ((tmp & 0x00FF0000) << (3*8)) |
218 ((tmp & 0x0000FF00) << (5*8)) |
219 ((tmp & 0x000000FF) << (7*8));
220}
[802]221
[2805]222//! \endcond
[1202]223
224uint_8 PIOPersist::Hash(string const& typname) {
225 md5_init(&ctx);
226 md5_write(&ctx, (unsigned char*) typname.c_str(), typname.size());
227 md5_final(&ctx);
228 uint_8 hash1 = *((uint_8*) ctx.buf);
229 uint_8 hash2 = *((uint_8*) (ctx.buf+8));
230#if IS_BIG_ENDIAN
[2476]231 bswap8_hash(&hash1);
232 bswap8_hash(&hash2);
[1202]233#endif
234
235 return (hash1+hash2);
236}
237
238
[219]239//++
240// Class PPersist
241// Lib Outils++
242// include ppersist.h
243//
244// Classe de base pour des objets persistants. Pour créer un objet
245// persistant :
246// - Hériter de PPersist.
247// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
248// membres que l'on souhaite écrire, et les relire dans le même ordre.
249// Pour écrire une référence à un objet : l'objet doit être un PPersist,
250// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
251// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
252// fois, il faut que cet objet soit un PShPersist.
253// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
254// les fonctions PutXX/GetXX de PInPersist/POutPersist.
255//
256// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
257// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
258//--
259
[2805]260/*!
261 \class SOPHYA::PPersist
262 \ingroup BaseTools
263 Ancestor (base) class for SOPHYA persistence (PPF) handlers.
264 In order to have provide a PPF handler for an object :
265 - Inherit from PPersist
266 - Implement WriteSelf() and ReadSelf()
267
268 \sa PInPersist POutPersist PIOPersist
269*/
270
271//! Writes the object into a new PPF file named \b fn
[219]272void
273PPersist::Write(string const& fn) const
274{
275 POutPersist of(fn);
276 Write(of);
277}
278
[2805]279//! Reads the object from a PInPersist stream created from file \b fn
[219]280void
281PPersist::Read(string const& fn)
282{
283 PInPersist inf(fn);
[2698]284 inf.SkipToNextObject();
[219]285 Read(inf);
286}
287
[2805]288//! Writes the object to the output PPF stream \b s
[219]289void
290PPersist::Write(POutPersist& s) const
291{
[802]292 s.PutPPObject(this);
[219]293}
294
295
[2805]296//! Reads the object from the input PPF stream \b s
[219]297void
298PPersist::Read(PInPersist& s)
299//
300// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
301// le type de l'objet. Pour une relecture avec création automatique du bon
[241]302// objet, utiliser PInPersist::ReadObject.
303// Il faut qu'on soit un objet ecrit
[219]304//--
305{
[241]306 // We should be the exact type
307 // Check tag value
[802]308 unsigned char ppstype,ppstag;
[588]309 s.GetTypeTag(ppstype);
[802]310 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
[241]311 }
[802]312 if (ppstype == PInPersist::PPS_OBJECT) {
313 // Check class id
314 uint_8 classId;
315 s.GetRawU8(classId);
316 uint_8 oid,oid2;
317 s.GetRawU8(oid);
318 if (classId != PIOPersist::getPPClassId(*this) )
319 throw FileFormatExc("PPersist::Read (): not the same object type");
320 ReadSelf(s);
321 // Read the ENDOBJECT
322 s.GetRawUByte(ppstag);
323 if (ppstag != PInPersist::PPS_ENDOBJECT)
324 throw FileFormatExc("PPersist::Read() No PPS_ENDOBJECT tag");
325 s.GetRawU8(oid2);
326 if (oid2 != oid)
327 throw FileFormatExc("PPersist::Read() Inconsistent PPS-OId at PPS_ENDOBJECT ");
328 s.KeepOId(oid, *this); // Object should be kept with its PPS_OId (if oid > 0)
[241]329 }
[802]330 else if ( ppstype == PInPersist::PPS_REFERENCE )
331 s.ReadReference(*this);
[219]332
[802]333 else throw FileFormatExc("PPersist::Read() : not an object in flow");
334
[219]335}
336
[2805]337//! Writes a name tag (\b tag) and then the object to the output PPF stream \b s
[241]338void
339PPersist::Write(POutPersist& s, string const& tag) const
[219]340{
[2441]341 s.WriteNameTag(tag);
[802]342 s.PutPPObject(this);
[219]343}
344
[2805]345//! Try to position at the name tag \b tag and then reads the object from the input stream \b s
[219]346void
[241]347PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]348{
[2459]349 if (!s.GotoNameTag(tag))
[241]350 throw NotFoundExc("PPersist::ReadAtTag tag not found");
351 Read(s);
[219]352}
353
[802]354// Renvoie l'identificateur de l'objet - par defaut=0
[2805]355/*! Return the object identifier (default: return 0)
356 (used for handling of PPF I/O for objects with reference sharing).
357*/
[802]358uint_8
359PPersist::getMemOId() const
360{
361 return(0);
362}
363
364// Ces deux methodes doivent etre redefinies si getMemOId() renvoie non nul (>0)
365// ShareDataReference() et CloneSharedReference()
[2805]366/*!
367 This method should be re-implemented if getMemOId() non zero value.
368 (used for handling of PPF I/O for objects with reference sharing).
369*/
[802]370void
371PPersist::ShareDataReference(PPersist & pcs)
372{
373 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
374}
375
[2805]376/*!
377 This method should be re-implemented if getMemOId() non zero value.
378 (used for handling of PPF I/O for objects with reference sharing).
379*/
[802]380PPersist *
381PPersist::CloneSharedReference()
382{
383 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
384}
385
[219]386//++
387// virtual void PPersist::ReadSelf(PInPersist&)=0
388// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
389// et PPersistMgr::ReadObject. Il faut relire les variables membres,
390// dans l'ordre où elles ont été écrites par WriteSelf.
391// virtual void PPersist::WriteSelf(POutPersist&) const=0
392// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
393// Il faut écrire les variables membres,
394// dans l'ordre où elles seront relues par ReadSelf.
395//--
396
397
398
399//++
400// Class PInPersist
401// Lib Outils++
402// include ppersist.h
403//
404// Fichier d'objets persistants, en lecture.
405//--
406
[2805]407/*!
408 \class SOPHYA::PInPersist
409 \ingroup BaseTools
410 This class implements the I/O read services necessary for SOPHYA
411 persistence (PPF) by extending the services provided by PPFBinaryInputStream.
412 \sa PPersist
413*/
414
415/*! Constructor from a RawInOutStream pointer
416 \param is : pointer to RawInOutStream
417 \param ad : if true, the RawInOutStream \b is is deleted by the destructor
418 \param scan : if true, try to read the name-tags table from the end of the input stream
419*/
[2482]420PInPersist::PInPersist(RawInOutStream * is, bool ad, bool scan)
421 : PPFBinaryInputStream(is, ad, scan)
422{
423}
424
[2805]425/*! Constructor
426 \param flnm : input file name
427 \param scan : if true, try to read the name-tags table from the end of the input stream
428*/
[219]429PInPersist::PInPersist(string const& flnm, bool scan)
[2475]430 : PPFBinaryInputStream(flnm, scan)
[219]431{
432}
433
434
435
436PInPersist::~PInPersist()
437{
[802]438 ObjList::iterator i;
439 for(i=objList.begin(); i!= objList.end(); i++)
440 if ((*i).second) delete (*i).second;
[219]441}
442
443
[802]444
[582]445string
[802]446PInPersist::GetTagClassName(int itag)
447{
448 // A faire
449// if (itag<0 || itag >= (int)tags.size()) return "";
450// map<string, int_8>::iterator i = tags.begin();
451// for (int j=0; j<itag; j++) i++;
452// uint_8 cid = (*i).second;
453// return(GetClassName(cid));
454 return("");
455}
456
[2805]457/*! Skip to next object in the streams, reads it and return
458 the corresponding PPersist handler
459*/
[241]460PPersist*
461PInPersist::ReadObject()
462{
[2698]463 SkipToNextObject();
[802]464 return(GetPPObject());
465}
466
[2805]467/*!
468 Tries to read in from the stream into object \b o
469*/
[802]470void
471PInPersist::GetObject(AnyDataObj & o)
472{
473 GetPPObject(&o);
474 return;
475}
476
[2805]477/*!
478 Tries to move to \b nametag and then read in from the stream into object \b o
479*/
[802]480void
481PInPersist::GetObject(AnyDataObj & o, string tagname)
482{
[2459]483 GotoNameTag(tagname);
[802]484 GetPPObject(&o);
485 return;
486}
487
[2805]488/*!
489 Reading of objects - used by GetObject() and ReadObject()
490*/
[802]491PPersist*
492PInPersist::GetPPObject(AnyDataObj * po)
493{
[241]494 // Get tag
[802]495 unsigned char ppstype;
[588]496 GetTypeTag(ppstype);
[241]497 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]498 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]499 }
500
501 if (ppstype == PPS_NULL) {
502 return NULL;
503 } else if (ppstype == PPS_OBJECT) {
504 // Get class id
505 uint_8 classId;
506 GetRawU8(classId);
[802]507 uint_8 oid,oid2;
508 GetRawU8(oid);
[241]509
510 // Get factory method
511 ClassCreatorFunc f = FindCreatorFunc(classId);
512 if (!f) {
513 throw NotFoundExc("PInPersist::ReadObject class not registered");
514 }
515
516 // Create object
517 PPersist* object = f();
[802]518 // If a DataObject was specified , we assign it to the PPersistObject
519 if (po != NULL) object->SetDataObj(*po);
520
[241]521 object->ReadSelf(*this);
[802]522 unsigned char ppstag;
523 // Read the ENDOBJECT
524 GetRawUByte(ppstag);
525 if (ppstag != PPS_ENDOBJECT)
526 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
527 GetRawU8(oid2);
528 if (oid2 != oid)
529 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
530
531 KeepOId(oid, *object);
[241]532 return object;
[802]533 }
[3426]534 else if (ppstype == PPS_REFERENCE) {
535 PPersist* ppr = ReadReference();
536 PPersist* pprc = ppr->CloneSharedReference();
537 if (po) { // We have to read it into an object
538 pprc->SetDataObj(*po);
539 pprc->ShareDataReference(*ppr); // On met a jour la reference de pprc
540 }
541 return pprc;
542 }
[802]543 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
544}
545
546
547
548void
549PInPersist::ReadReference(PPersist & ppo)
[241]550{
[802]551 PPersist * pr = ReadReference();
552 ppo.ShareDataReference(*pr);
[241]553}
554
[802]555
556PPersist *
557PInPersist::ReadReference()
558{
559 uint_8 oid;
560 int_8 pos;
561 GetRawU8(oid);
562 GetRawI8(pos);
563 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
564 map<uint_8, PPersist *>::iterator i = objList.find(oid);
565 if (i != objList.end()) return (*i).second;
566 else { // We may have skeeped it !
567 // Let's try to read it
568 int_8 cpos;
569 cpos = s->tellg();
570 s->seekg(pos);
571 PPersist* ppo = ReadObject();
572 s->seekg(cpos);
573 delete ppo;
574 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
575
576 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
577 if (i2 == objList.end())
578 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
579 return (*i2).second;
580 }
581}
582
583
584void
585PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
586{
587 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
588 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
589 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
[2459]590 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
[802]591 // et pas avec une lecture sequentielle ... Reza 03/2000
592 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
593 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
594 PPersist *pp = (*objList.find(oid)).second;
[3426]595 ppo.ShareDataReference(*pp); // On met a jour la reference des donnees de ppo
[802]596 }
597 else {
598 PPersist * npp = ppo.CloneSharedReference();
599 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
600 objList[oid] = npp;
601 }
602 return;
603}
604
[219]605//++
606// Class POutPersist
607// Lib Outils++
608// include ppersist.h
609//
610// Fichier d'objets persistants, en écriture.
611//--
612
613
[2805]614/*!
615 \class SOPHYA::POutPersist
616 \ingroup BaseTools
617 This class implements the I/O write services necessary for SOPHYA
618 persistence (PPF) by extending the services provided by PPFBinaryOutputStream.
619 \sa PPersist
620*/
621
[219]622//++
623// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
624//
625// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
626// sur machines petit-boutiennes, et gros-boutien sur machines
627// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
628// ou PPersist::PPS_BIG_ENDIAN.
629//--
[2805]630
631/*! Constructor from a RawInOutStream pointer
632 \param os : pointer to RawInOutStream
633 \param ad : if true, the RawInOutStream \b os is deleted by the destructor
634 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
635*/
[2477]636POutPersist::POutPersist(RawInOutStream* os, bool ad, int endianness)
637 : PPFBinaryOutputStream(os, ad, endianness)
638{
639 pps_OId = 0;
640 wobj_level = 0;
641}
642
[2805]643/*! Constructor
644 \param flnm : output file name
645 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
646*/
[219]647POutPersist::POutPersist(string const& flnm, int endianness)
[2475]648 : PPFBinaryOutputStream(flnm, endianness)
[219]649{
[802]650 // PPS (POutPersist stream) Object Id initialisation
651 pps_OId = 0;
[2477]652 wobj_level = 0;
[219]653}
654
655POutPersist::~POutPersist()
656{
657}
658
659
[2805]660//! Writes the object \b o to the stream
[241]661void
[802]662POutPersist::PutObject(AnyDataObj & o)
663{
664 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
665 if (!f)
[3426]666 throw NotFoundExc("POutPersist::PutObject() class not registered");
[802]667 PPersist* ppo = f();
668 ppo->SetDataObj(o);
669 PutPPObject(ppo);
[219]670}
671
[2805]672//! Writes the nametag \b tagname and then the object \b o to the stream
[241]673void
[802]674POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]675{
[2441]676 WriteNameTag(tagname);
[802]677 PutObject(o);
678}
[219]679
[802]680
681void
682POutPersist::PutPPObject(PPersist const* obj)
683{
684 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
685
686 // We have to write the object
687 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
688 PutRawUByte(PPS_OBJECT); // We write the Object Tag
[2477]689 wobj_level++; // Niveau d'imbrication d'ecriture d'objets
[802]690 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
691 PutRawU8(oid); // Write the PPS Object Id
[241]692 obj->WriteSelf(*this);
[2477]693 // Comptage d'objets ecrits
694 _nbobjs++;
[2482]695 if (wobj_level > _maxnestlevel) _maxnestlevel = wobj_level;
[2477]696 if (wobj_level == 1) _nbtlobjs++;
697 wobj_level--;
[802]698 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
699 PutRawU8(oid); // and again its PPS Object Id
[241]700}
[219]701
[241]702bool
703POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]704{
[241]705 if (x == NULL) {
[802]706 PutRawUByte(PPS_NULL);
[241]707 return true;
708 }
[219]709
[802]710 int_8 pos;
711 uint_8 id = findObjectId(x, pos);
712 if (id > 0) {
713 PutRawUByte(PPS_REFERENCE);
714 PutRawU8(id); // Writing the corresponding object Id
715 PutRawI8(pos); // The original object position
[2482]716 _nbrefs++; // Compteur de nombre de reference ecrits
[241]717 return true;
718 }
[219]719
[802]720 return false; // Object have to be written in stream ...
[219]721}
722
[802]723uint_8
[241]724POutPersist::assignObjectId(PPersist const* x)
[219]725{
[802]726 pps_OId += 16; // We keep the three first bytes for future usage
727 // Bit 1 non zero -> Object can be referenced
728 uint_8 id = pps_OId;
729 uint_8 mid = x->getMemOId();
730 if (mid > 0) {
731 int_8 pos;
732 if (findObjectId(x,pos) > 0)
733 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
[821]734 id += 1; // Bit 1 non zero -> Object can be referenced
[802]735 objreftag rt;
736 rt.ppsoid = id;
[2476]737 // cout << " DBG-rt.ppspos = s->tellp(); " << endl;
[802]738 rt.ppspos = s->tellp();
[2476]739 // cout << " DBG-rt.ppspos = s->tellp(); = " << rt.ppspos << endl;
[802]740 objList[mid] = rt;
741 }
[241]742 return id;
[219]743}
744
[802]745uint_8
746POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]747{
[802]748 pos = -1;
749 uint_8 mid = x->getMemOId();
750 if (mid == 0) return(0);
751 ObjList::iterator i = objList.find(mid);
752 if (i == objList.end()) return 0;
753 pos = (*i).second.ppspos;
754 return (*i).second.ppsoid;
[219]755}
756
[241]757
Note: See TracBrowser for help on using the repository browser.