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

Last change on this file 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
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <stdio.h>
4#include <sys/types.h>
5#include <time.h>
6#include "pexceptions.h"
7#include "ppersist.h"
8#include "anydataobj.h"
9#include <iostream>
10#include <iomanip>
11#include <typeinfo>
12
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// -----------------------------------------------------------------
21
22
23
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
32//++
33// Class PIOPersist
34// Lib Outils++
35// include ppersist.h
36//
37// Root class for persistant files. Handles the registration of
38// persistant classes
39//--
40
41MD5_CONTEXT PIOPersist::ctx;
42PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
43map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
44map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
45
46//++
47void
48PIOPersist::Initialize()
49// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
50//--
51{
52ppclassList = new PIOPersist::ClassList;
53ppclassNameList = new map<string, uint_8>;
54dobjclassNameList = new map<string, uint_8>;
55cout << " PIOPersist::Initialize() Starting Sophya Persistence management service " << endl;
56}
57
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*/
64void
65PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
66{
67 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
68 cerr << "RegisterClass : Error, " << hex << classId << dec
69 << " already registered." << endl;
70 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
71 }
72 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
73 cerr << "RegisterClass : Error (2) " << ppclass_name
74 << " already registered." << endl;
75 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
76 }
77
78 (*ppclassList)[classId] = f;
79 (*ppclassNameList)[ppclass_name] = classId;
80}
81
82/*!
83 Register a new DataObj class corresponding to a PPersist classId
84 class_typename should be typeid(DataObject).name()
85*/
86void
87PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
88{
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 }
99
100 (*dobjclassNameList)[class_name] = classId;
101}
102
103// class_typename should be typeid(DataObject).name(), to be
104// used by POutPersist::PutDataObject() methods.
105
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
131//! Returns the PPersist class creator function for the specified classId
132PIOPersist::ClassCreatorFunc
133PIOPersist::FindCreatorFunc(uint_8 classId)
134{
135 ClassList::iterator i = ppclassList->find(classId);
136 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
137 return (*i).second;
138}
139
140//! Returns the PPersist class name for the specified classId
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;
147
148 throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
149}
150
151//! Returns the classId for the specified PPersist class type name
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
161//! Returns the classId for the specified PPersist class
162uint_8
163PIOPersist::getPPClassId(PPersist const & ppo)
164{
165 string typ_name = typeid(ppo).name() ;
166 return (getPPClassId(typ_name) );
167}
168
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}
178
179//! Returns the PPersist class name for the specified classId
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
190//! Returns the classId for the specified PPersist class type name
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
200//! Returns the classId for the specified PPersist class
201uint_8
202PIOPersist::getDataObjClassId(AnyDataObj const & o)
203{
204 string typ_name = typeid(o).name() ;
205 return (getDataObjClassId(typ_name) );
206}
207
208//! \cond
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}
221
222//! \endcond
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
231 bswap8_hash(&hash1);
232 bswap8_hash(&hash2);
233#endif
234
235 return (hash1+hash2);
236}
237
238
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
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
272void
273PPersist::Write(string const& fn) const
274{
275 POutPersist of(fn);
276 Write(of);
277}
278
279//! Reads the object from a PInPersist stream created from file \b fn
280void
281PPersist::Read(string const& fn)
282{
283 PInPersist inf(fn);
284 inf.SkipToNextObject();
285 Read(inf);
286}
287
288//! Writes the object to the output PPF stream \b s
289void
290PPersist::Write(POutPersist& s) const
291{
292 s.PutPPObject(this);
293}
294
295
296//! Reads the object from the input PPF stream \b s
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
302// objet, utiliser PInPersist::ReadObject.
303// Il faut qu'on soit un objet ecrit
304//--
305{
306 // We should be the exact type
307 // Check tag value
308 unsigned char ppstype,ppstag;
309 s.GetTypeTag(ppstype);
310 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
311 }
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)
329 }
330 else if ( ppstype == PInPersist::PPS_REFERENCE )
331 s.ReadReference(*this);
332
333 else throw FileFormatExc("PPersist::Read() : not an object in flow");
334
335}
336
337//! Writes a name tag (\b tag) and then the object to the output PPF stream \b s
338void
339PPersist::Write(POutPersist& s, string const& tag) const
340{
341 s.WriteNameTag(tag);
342 s.PutPPObject(this);
343}
344
345//! Try to position at the name tag \b tag and then reads the object from the input stream \b s
346void
347PPersist::ReadAtTag(PInPersist& s, string const& tag)
348{
349 if (!s.GotoNameTag(tag))
350 throw NotFoundExc("PPersist::ReadAtTag tag not found");
351 Read(s);
352}
353
354// Renvoie l'identificateur de l'objet - par defaut=0
355/*! Return the object identifier (default: return 0)
356 (used for handling of PPF I/O for objects with reference sharing).
357*/
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()
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*/
370void
371PPersist::ShareDataReference(PPersist & pcs)
372{
373 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
374}
375
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*/
380PPersist *
381PPersist::CloneSharedReference()
382{
383 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
384}
385
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
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*/
420PInPersist::PInPersist(RawInOutStream * is, bool ad, bool scan)
421 : PPFBinaryInputStream(is, ad, scan)
422{
423}
424
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*/
429PInPersist::PInPersist(string const& flnm, bool scan)
430 : PPFBinaryInputStream(flnm, scan)
431{
432}
433
434
435
436PInPersist::~PInPersist()
437{
438 ObjList::iterator i;
439 for(i=objList.begin(); i!= objList.end(); i++)
440 if ((*i).second) delete (*i).second;
441}
442
443
444
445string
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
457/*! Skip to next object in the streams, reads it and return
458 the corresponding PPersist handler
459*/
460PPersist*
461PInPersist::ReadObject()
462{
463 SkipToNextObject();
464 return(GetPPObject());
465}
466
467/*!
468 Tries to read in from the stream into object \b o
469*/
470void
471PInPersist::GetObject(AnyDataObj & o)
472{
473 GetPPObject(&o);
474 return;
475}
476
477/*!
478 Tries to move to \b nametag and then read in from the stream into object \b o
479*/
480void
481PInPersist::GetObject(AnyDataObj & o, string tagname)
482{
483 GotoNameTag(tagname);
484 GetPPObject(&o);
485 return;
486}
487
488/*!
489 Reading of objects - used by GetObject() and ReadObject()
490*/
491PPersist*
492PInPersist::GetPPObject(AnyDataObj * po)
493{
494 // Get tag
495 unsigned char ppstype;
496 GetTypeTag(ppstype);
497 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
498 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
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);
507 uint_8 oid,oid2;
508 GetRawU8(oid);
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();
518 // If a DataObject was specified , we assign it to the PPersistObject
519 if (po != NULL) object->SetDataObj(*po);
520
521 object->ReadSelf(*this);
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);
532 return object;
533 }
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 }
543 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
544}
545
546
547
548void
549PInPersist::ReadReference(PPersist & ppo)
550{
551 PPersist * pr = ReadReference();
552 ppo.ShareDataReference(*pr);
553}
554
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()) ) {
590 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
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;
595 ppo.ShareDataReference(*pp); // On met a jour la reference des donnees de ppo
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
605//++
606// Class POutPersist
607// Lib Outils++
608// include ppersist.h
609//
610// Fichier d'objets persistants, en écriture.
611//--
612
613
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
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//--
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*/
636POutPersist::POutPersist(RawInOutStream* os, bool ad, int endianness)
637 : PPFBinaryOutputStream(os, ad, endianness)
638{
639 pps_OId = 0;
640 wobj_level = 0;
641}
642
643/*! Constructor
644 \param flnm : output file name
645 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
646*/
647POutPersist::POutPersist(string const& flnm, int endianness)
648 : PPFBinaryOutputStream(flnm, endianness)
649{
650 // PPS (POutPersist stream) Object Id initialisation
651 pps_OId = 0;
652 wobj_level = 0;
653}
654
655POutPersist::~POutPersist()
656{
657}
658
659
660//! Writes the object \b o to the stream
661void
662POutPersist::PutObject(AnyDataObj & o)
663{
664 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
665 if (!f)
666 throw NotFoundExc("POutPersist::PutObject() class not registered");
667 PPersist* ppo = f();
668 ppo->SetDataObj(o);
669 PutPPObject(ppo);
670}
671
672//! Writes the nametag \b tagname and then the object \b o to the stream
673void
674POutPersist::PutObject(AnyDataObj & o, string tagname)
675{
676 WriteNameTag(tagname);
677 PutObject(o);
678}
679
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
689 wobj_level++; // Niveau d'imbrication d'ecriture d'objets
690 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
691 PutRawU8(oid); // Write the PPS Object Id
692 obj->WriteSelf(*this);
693 // Comptage d'objets ecrits
694 _nbobjs++;
695 if (wobj_level > _maxnestlevel) _maxnestlevel = wobj_level;
696 if (wobj_level == 1) _nbtlobjs++;
697 wobj_level--;
698 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
699 PutRawU8(oid); // and again its PPS Object Id
700}
701
702bool
703POutPersist::serializeNullAndRepeat(PPersist const* x)
704{
705 if (x == NULL) {
706 PutRawUByte(PPS_NULL);
707 return true;
708 }
709
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
716 _nbrefs++; // Compteur de nombre de reference ecrits
717 return true;
718 }
719
720 return false; // Object have to be written in stream ...
721}
722
723uint_8
724POutPersist::assignObjectId(PPersist const* x)
725{
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 ! ");
734 id += 1; // Bit 1 non zero -> Object can be referenced
735 objreftag rt;
736 rt.ppsoid = id;
737 // cout << " DBG-rt.ppspos = s->tellp(); " << endl;
738 rt.ppspos = s->tellp();
739 // cout << " DBG-rt.ppspos = s->tellp(); = " << rt.ppspos << endl;
740 objList[mid] = rt;
741 }
742 return id;
743}
744
745uint_8
746POutPersist::findObjectId(PPersist const* x, int_8 & pos)
747{
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;
755}
756
757
Note: See TracBrowser for help on using the repository browser.