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

Last change on this file since 3844 was 3426, checked in by ansari, 18 years ago

Correction bug (delete objet deja supprime ds ~PInPersist - lie a bug ds ReadReference() - Reza 08/12/2007

File size: 21.5 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
170//! Returns the PPersist class name for the specified classId
171string
172PIOPersist::getDataObjClassName(uint_8 classId)
173{
174 map<string, uint_8>::iterator i;
175 for (i= dobjclassNameList->begin(); i != dobjclassNameList->end(); i++)
176 if ( (*i).second == classId ) return (*i).first;
177
178 throw(NotFoundExc("PIOPersist::getDataObjClassName() Not found classId"));
179}
180
181//! Returns the classId for the specified PPersist class type name
182uint_8
183PIOPersist::getDataObjClassId(string const & typ_name)
184{
185 map<string, uint_8>::iterator i = dobjclassNameList->find(typ_name);
186 if (i == dobjclassNameList->end())
187 throw(NotFoundExc("PIOPersist::getDataObjClassId() Not found className"));
188 return (*i).second;
189}
190
191//! Returns the classId for the specified PPersist class
192uint_8
193PIOPersist::getDataObjClassId(AnyDataObj const & o)
194{
195 string typ_name = typeid(o).name() ;
196 return (getDataObjClassId(typ_name) );
197}
198
199//! \cond
200static inline void bswap8_hash(void* p)
201{
202 uint_8 tmp = *(uint_8*)p;
203 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
204 ((tmp >> (5*8)) & 0x0000FF00) |
205 ((tmp >> (3*8)) & 0x00FF0000) |
206 ((tmp >> (1*8)) & 0xFF000000) |
207 ((tmp & 0xFF000000) << (1*8)) |
208 ((tmp & 0x00FF0000) << (3*8)) |
209 ((tmp & 0x0000FF00) << (5*8)) |
210 ((tmp & 0x000000FF) << (7*8));
211}
212
213//! \endcond
214
215uint_8 PIOPersist::Hash(string const& typname) {
216 md5_init(&ctx);
217 md5_write(&ctx, (unsigned char*) typname.c_str(), typname.size());
218 md5_final(&ctx);
219 uint_8 hash1 = *((uint_8*) ctx.buf);
220 uint_8 hash2 = *((uint_8*) (ctx.buf+8));
221#if IS_BIG_ENDIAN
222 bswap8_hash(&hash1);
223 bswap8_hash(&hash2);
224#endif
225
226 return (hash1+hash2);
227}
228
229
230//++
231// Class PPersist
232// Lib Outils++
233// include ppersist.h
234//
235// Classe de base pour des objets persistants. Pour créer un objet
236// persistant :
237// - Hériter de PPersist.
238// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
239// membres que l'on souhaite écrire, et les relire dans le même ordre.
240// Pour écrire une référence à un objet : l'objet doit être un PPersist,
241// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
242// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
243// fois, il faut que cet objet soit un PShPersist.
244// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
245// les fonctions PutXX/GetXX de PInPersist/POutPersist.
246//
247// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
248// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
249//--
250
251/*!
252 \class SOPHYA::PPersist
253 \ingroup BaseTools
254 Ancestor (base) class for SOPHYA persistence (PPF) handlers.
255 In order to have provide a PPF handler for an object :
256 - Inherit from PPersist
257 - Implement WriteSelf() and ReadSelf()
258
259 \sa PInPersist POutPersist PIOPersist
260*/
261
262//! Writes the object into a new PPF file named \b fn
263void
264PPersist::Write(string const& fn) const
265{
266 POutPersist of(fn);
267 Write(of);
268}
269
270//! Reads the object from a PInPersist stream created from file \b fn
271void
272PPersist::Read(string const& fn)
273{
274 PInPersist inf(fn);
275 inf.SkipToNextObject();
276 Read(inf);
277}
278
279//! Writes the object to the output PPF stream \b s
280void
281PPersist::Write(POutPersist& s) const
282{
283 s.PutPPObject(this);
284}
285
286
287//! Reads the object from the input PPF stream \b s
288void
289PPersist::Read(PInPersist& s)
290//
291// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
292// le type de l'objet. Pour une relecture avec création automatique du bon
293// objet, utiliser PInPersist::ReadObject.
294// Il faut qu'on soit un objet ecrit
295//--
296{
297 // We should be the exact type
298 // Check tag value
299 unsigned char ppstype,ppstag;
300 s.GetTypeTag(ppstype);
301 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
302 }
303 if (ppstype == PInPersist::PPS_OBJECT) {
304 // Check class id
305 uint_8 classId;
306 s.GetRawU8(classId);
307 uint_8 oid,oid2;
308 s.GetRawU8(oid);
309 if (classId != PIOPersist::getPPClassId(*this) )
310 throw FileFormatExc("PPersist::Read (): not the same object type");
311 ReadSelf(s);
312 // Read the ENDOBJECT
313 s.GetRawUByte(ppstag);
314 if (ppstag != PInPersist::PPS_ENDOBJECT)
315 throw FileFormatExc("PPersist::Read() No PPS_ENDOBJECT tag");
316 s.GetRawU8(oid2);
317 if (oid2 != oid)
318 throw FileFormatExc("PPersist::Read() Inconsistent PPS-OId at PPS_ENDOBJECT ");
319 s.KeepOId(oid, *this); // Object should be kept with its PPS_OId (if oid > 0)
320 }
321 else if ( ppstype == PInPersist::PPS_REFERENCE )
322 s.ReadReference(*this);
323
324 else throw FileFormatExc("PPersist::Read() : not an object in flow");
325
326}
327
328//! Writes a name tag (\b tag) and then the object to the output PPF stream \b s
329void
330PPersist::Write(POutPersist& s, string const& tag) const
331{
332 s.WriteNameTag(tag);
333 s.PutPPObject(this);
334}
335
336//! Try to position at the name tag \b tag and then reads the object from the input stream \b s
337void
338PPersist::ReadAtTag(PInPersist& s, string const& tag)
339{
340 if (!s.GotoNameTag(tag))
341 throw NotFoundExc("PPersist::ReadAtTag tag not found");
342 Read(s);
343}
344
345// Renvoie l'identificateur de l'objet - par defaut=0
346/*! Return the object identifier (default: return 0)
347 (used for handling of PPF I/O for objects with reference sharing).
348*/
349uint_8
350PPersist::getMemOId() const
351{
352 return(0);
353}
354
355// Ces deux methodes doivent etre redefinies si getMemOId() renvoie non nul (>0)
356// ShareDataReference() et CloneSharedReference()
357/*!
358 This method should be re-implemented if getMemOId() non zero value.
359 (used for handling of PPF I/O for objects with reference sharing).
360*/
361void
362PPersist::ShareDataReference(PPersist & pcs)
363{
364 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
365}
366
367/*!
368 This method should be re-implemented if getMemOId() non zero value.
369 (used for handling of PPF I/O for objects with reference sharing).
370*/
371PPersist *
372PPersist::CloneSharedReference()
373{
374 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
375}
376
377//++
378// virtual void PPersist::ReadSelf(PInPersist&)=0
379// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
380// et PPersistMgr::ReadObject. Il faut relire les variables membres,
381// dans l'ordre où elles ont été écrites par WriteSelf.
382// virtual void PPersist::WriteSelf(POutPersist&) const=0
383// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
384// Il faut écrire les variables membres,
385// dans l'ordre où elles seront relues par ReadSelf.
386//--
387
388
389
390//++
391// Class PInPersist
392// Lib Outils++
393// include ppersist.h
394//
395// Fichier d'objets persistants, en lecture.
396//--
397
398/*!
399 \class SOPHYA::PInPersist
400 \ingroup BaseTools
401 This class implements the I/O read services necessary for SOPHYA
402 persistence (PPF) by extending the services provided by PPFBinaryInputStream.
403 \sa PPersist
404*/
405
406/*! Constructor from a RawInOutStream pointer
407 \param is : pointer to RawInOutStream
408 \param ad : if true, the RawInOutStream \b is is deleted by the destructor
409 \param scan : if true, try to read the name-tags table from the end of the input stream
410*/
411PInPersist::PInPersist(RawInOutStream * is, bool ad, bool scan)
412 : PPFBinaryInputStream(is, ad, scan)
413{
414}
415
416/*! Constructor
417 \param flnm : input file name
418 \param scan : if true, try to read the name-tags table from the end of the input stream
419*/
420PInPersist::PInPersist(string const& flnm, bool scan)
421 : PPFBinaryInputStream(flnm, scan)
422{
423}
424
425
426
427PInPersist::~PInPersist()
428{
429 ObjList::iterator i;
430 for(i=objList.begin(); i!= objList.end(); i++)
431 if ((*i).second) delete (*i).second;
432}
433
434
435
436string
437PInPersist::GetTagClassName(int itag)
438{
439 // A faire
440// if (itag<0 || itag >= (int)tags.size()) return "";
441// map<string, int_8>::iterator i = tags.begin();
442// for (int j=0; j<itag; j++) i++;
443// uint_8 cid = (*i).second;
444// return(GetClassName(cid));
445 return("");
446}
447
448/*! Skip to next object in the streams, reads it and return
449 the corresponding PPersist handler
450*/
451PPersist*
452PInPersist::ReadObject()
453{
454 SkipToNextObject();
455 return(GetPPObject());
456}
457
458/*!
459 Tries to read in from the stream into object \b o
460*/
461void
462PInPersist::GetObject(AnyDataObj & o)
463{
464 GetPPObject(&o);
465 return;
466}
467
468/*!
469 Tries to move to \b nametag and then read in from the stream into object \b o
470*/
471void
472PInPersist::GetObject(AnyDataObj & o, string tagname)
473{
474 GotoNameTag(tagname);
475 GetPPObject(&o);
476 return;
477}
478
479/*!
480 Reading of objects - used by GetObject() and ReadObject()
481*/
482PPersist*
483PInPersist::GetPPObject(AnyDataObj * po)
484{
485 // Get tag
486 unsigned char ppstype;
487 GetTypeTag(ppstype);
488 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
489 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
490 }
491
492 if (ppstype == PPS_NULL) {
493 return NULL;
494 } else if (ppstype == PPS_OBJECT) {
495 // Get class id
496 uint_8 classId;
497 GetRawU8(classId);
498 uint_8 oid,oid2;
499 GetRawU8(oid);
500
501 // Get factory method
502 ClassCreatorFunc f = FindCreatorFunc(classId);
503 if (!f) {
504 throw NotFoundExc("PInPersist::ReadObject class not registered");
505 }
506
507 // Create object
508 PPersist* object = f();
509 // If a DataObject was specified , we assign it to the PPersistObject
510 if (po != NULL) object->SetDataObj(*po);
511
512 object->ReadSelf(*this);
513 unsigned char ppstag;
514 // Read the ENDOBJECT
515 GetRawUByte(ppstag);
516 if (ppstag != PPS_ENDOBJECT)
517 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
518 GetRawU8(oid2);
519 if (oid2 != oid)
520 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
521
522 KeepOId(oid, *object);
523 return object;
524 }
525 else if (ppstype == PPS_REFERENCE) {
526 PPersist* ppr = ReadReference();
527 PPersist* pprc = ppr->CloneSharedReference();
528 if (po) { // We have to read it into an object
529 pprc->SetDataObj(*po);
530 pprc->ShareDataReference(*ppr); // On met a jour la reference de pprc
531 }
532 return pprc;
533 }
534 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
535}
536
537
538
539void
540PInPersist::ReadReference(PPersist & ppo)
541{
542 PPersist * pr = ReadReference();
543 ppo.ShareDataReference(*pr);
544}
545
546
547PPersist *
548PInPersist::ReadReference()
549{
550 uint_8 oid;
551 int_8 pos;
552 GetRawU8(oid);
553 GetRawI8(pos);
554 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
555 map<uint_8, PPersist *>::iterator i = objList.find(oid);
556 if (i != objList.end()) return (*i).second;
557 else { // We may have skeeped it !
558 // Let's try to read it
559 int_8 cpos;
560 cpos = s->tellg();
561 s->seekg(pos);
562 PPersist* ppo = ReadObject();
563 s->seekg(cpos);
564 delete ppo;
565 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
566
567 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
568 if (i2 == objList.end())
569 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
570 return (*i2).second;
571 }
572}
573
574
575void
576PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
577{
578 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
579 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
580 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
581 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
582 // et pas avec une lecture sequentielle ... Reza 03/2000
583 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
584 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
585 PPersist *pp = (*objList.find(oid)).second;
586 ppo.ShareDataReference(*pp); // On met a jour la reference des donnees de ppo
587 }
588 else {
589 PPersist * npp = ppo.CloneSharedReference();
590 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
591 objList[oid] = npp;
592 }
593 return;
594}
595
596//++
597// Class POutPersist
598// Lib Outils++
599// include ppersist.h
600//
601// Fichier d'objets persistants, en écriture.
602//--
603
604
605/*!
606 \class SOPHYA::POutPersist
607 \ingroup BaseTools
608 This class implements the I/O write services necessary for SOPHYA
609 persistence (PPF) by extending the services provided by PPFBinaryOutputStream.
610 \sa PPersist
611*/
612
613//++
614// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
615//
616// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
617// sur machines petit-boutiennes, et gros-boutien sur machines
618// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
619// ou PPersist::PPS_BIG_ENDIAN.
620//--
621
622/*! Constructor from a RawInOutStream pointer
623 \param os : pointer to RawInOutStream
624 \param ad : if true, the RawInOutStream \b os is deleted by the destructor
625 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
626*/
627POutPersist::POutPersist(RawInOutStream* os, bool ad, int endianness)
628 : PPFBinaryOutputStream(os, ad, endianness)
629{
630 pps_OId = 0;
631 wobj_level = 0;
632}
633
634/*! Constructor
635 \param flnm : output file name
636 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
637*/
638POutPersist::POutPersist(string const& flnm, int endianness)
639 : PPFBinaryOutputStream(flnm, endianness)
640{
641 // PPS (POutPersist stream) Object Id initialisation
642 pps_OId = 0;
643 wobj_level = 0;
644}
645
646POutPersist::~POutPersist()
647{
648}
649
650
651//! Writes the object \b o to the stream
652void
653POutPersist::PutObject(AnyDataObj & o)
654{
655 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
656 if (!f)
657 throw NotFoundExc("POutPersist::PutObject() class not registered");
658 PPersist* ppo = f();
659 ppo->SetDataObj(o);
660 PutPPObject(ppo);
661}
662
663//! Writes the nametag \b tagname and then the object \b o to the stream
664void
665POutPersist::PutObject(AnyDataObj & o, string tagname)
666{
667 WriteNameTag(tagname);
668 PutObject(o);
669}
670
671
672void
673POutPersist::PutPPObject(PPersist const* obj)
674{
675 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
676
677 // We have to write the object
678 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
679 PutRawUByte(PPS_OBJECT); // We write the Object Tag
680 wobj_level++; // Niveau d'imbrication d'ecriture d'objets
681 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
682 PutRawU8(oid); // Write the PPS Object Id
683 obj->WriteSelf(*this);
684 // Comptage d'objets ecrits
685 _nbobjs++;
686 if (wobj_level > _maxnestlevel) _maxnestlevel = wobj_level;
687 if (wobj_level == 1) _nbtlobjs++;
688 wobj_level--;
689 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
690 PutRawU8(oid); // and again its PPS Object Id
691}
692
693bool
694POutPersist::serializeNullAndRepeat(PPersist const* x)
695{
696 if (x == NULL) {
697 PutRawUByte(PPS_NULL);
698 return true;
699 }
700
701 int_8 pos;
702 uint_8 id = findObjectId(x, pos);
703 if (id > 0) {
704 PutRawUByte(PPS_REFERENCE);
705 PutRawU8(id); // Writing the corresponding object Id
706 PutRawI8(pos); // The original object position
707 _nbrefs++; // Compteur de nombre de reference ecrits
708 return true;
709 }
710
711 return false; // Object have to be written in stream ...
712}
713
714uint_8
715POutPersist::assignObjectId(PPersist const* x)
716{
717 pps_OId += 16; // We keep the three first bytes for future usage
718 // Bit 1 non zero -> Object can be referenced
719 uint_8 id = pps_OId;
720 uint_8 mid = x->getMemOId();
721 if (mid > 0) {
722 int_8 pos;
723 if (findObjectId(x,pos) > 0)
724 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
725 id += 1; // Bit 1 non zero -> Object can be referenced
726 objreftag rt;
727 rt.ppsoid = id;
728 // cout << " DBG-rt.ppspos = s->tellp(); " << endl;
729 rt.ppspos = s->tellp();
730 // cout << " DBG-rt.ppspos = s->tellp(); = " << rt.ppspos << endl;
731 objList[mid] = rt;
732 }
733 return id;
734}
735
736uint_8
737POutPersist::findObjectId(PPersist const* x, int_8 & pos)
738{
739 pos = -1;
740 uint_8 mid = x->getMemOId();
741 if (mid == 0) return(0);
742 ObjList::iterator i = objList.find(mid);
743 if (i == objList.end()) return 0;
744 pos = (*i).second.ppspos;
745 return (*i).second.ppsoid;
746}
747
748
Note: See TracBrowser for help on using the repository browser.