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

Last change on this file since 4051 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.