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

Last change on this file since 3293 was 2805, checked in by ansari, 20 years ago

MAJ commentaires pour documentation doxygen - Reza 9 Juin 2005

File size: 21.2 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 return ReadReference();
527
528 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
529}
530
531
532
533void
534PInPersist::ReadReference(PPersist & ppo)
535{
536 PPersist * pr = ReadReference();
537 ppo.ShareDataReference(*pr);
538}
539
540
541PPersist *
542PInPersist::ReadReference()
543{
544 uint_8 oid;
545 int_8 pos;
546 GetRawU8(oid);
547 GetRawI8(pos);
548 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
549 map<uint_8, PPersist *>::iterator i = objList.find(oid);
550 if (i != objList.end()) return (*i).second;
551 else { // We may have skeeped it !
552 // Let's try to read it
553 int_8 cpos;
554 cpos = s->tellg();
555 s->seekg(pos);
556 PPersist* ppo = ReadObject();
557 s->seekg(cpos);
558 delete ppo;
559 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
560
561 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
562 if (i2 == objList.end())
563 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
564 return (*i2).second;
565 }
566}
567
568
569void
570PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
571{
572 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
573 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
574 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
575 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
576 // et pas avec une lecture sequentielle ... Reza 03/2000
577 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
578 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
579 PPersist *pp = (*objList.find(oid)).second;
580 ppo.ShareDataReference(*pp);
581 }
582 else {
583 PPersist * npp = ppo.CloneSharedReference();
584 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
585 objList[oid] = npp;
586 }
587 return;
588}
589
590//++
591// Class POutPersist
592// Lib Outils++
593// include ppersist.h
594//
595// Fichier d'objets persistants, en écriture.
596//--
597
598
599/*!
600 \class SOPHYA::POutPersist
601 \ingroup BaseTools
602 This class implements the I/O write services necessary for SOPHYA
603 persistence (PPF) by extending the services provided by PPFBinaryOutputStream.
604 \sa PPersist
605*/
606
607//++
608// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
609//
610// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
611// sur machines petit-boutiennes, et gros-boutien sur machines
612// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
613// ou PPersist::PPS_BIG_ENDIAN.
614//--
615
616/*! Constructor from a RawInOutStream pointer
617 \param os : pointer to RawInOutStream
618 \param ad : if true, the RawInOutStream \b os is deleted by the destructor
619 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
620*/
621POutPersist::POutPersist(RawInOutStream* os, bool ad, int endianness)
622 : PPFBinaryOutputStream(os, ad, endianness)
623{
624 pps_OId = 0;
625 wobj_level = 0;
626}
627
628/*! Constructor
629 \param flnm : output file name
630 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
631*/
632POutPersist::POutPersist(string const& flnm, int endianness)
633 : PPFBinaryOutputStream(flnm, endianness)
634{
635 // PPS (POutPersist stream) Object Id initialisation
636 pps_OId = 0;
637 wobj_level = 0;
638}
639
640POutPersist::~POutPersist()
641{
642}
643
644
645//! Writes the object \b o to the stream
646void
647POutPersist::PutObject(AnyDataObj & o)
648{
649 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
650 if (!f)
651 throw NotFoundExc("PInPersist::PutObject() class not registered");
652 PPersist* ppo = f();
653 ppo->SetDataObj(o);
654 PutPPObject(ppo);
655}
656
657//! Writes the nametag \b tagname and then the object \b o to the stream
658void
659POutPersist::PutObject(AnyDataObj & o, string tagname)
660{
661 WriteNameTag(tagname);
662 PutObject(o);
663}
664
665
666void
667POutPersist::PutPPObject(PPersist const* obj)
668{
669 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
670
671 // We have to write the object
672 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
673 PutRawUByte(PPS_OBJECT); // We write the Object Tag
674 wobj_level++; // Niveau d'imbrication d'ecriture d'objets
675 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
676 PutRawU8(oid); // Write the PPS Object Id
677 obj->WriteSelf(*this);
678 // Comptage d'objets ecrits
679 _nbobjs++;
680 if (wobj_level > _maxnestlevel) _maxnestlevel = wobj_level;
681 if (wobj_level == 1) _nbtlobjs++;
682 wobj_level--;
683 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
684 PutRawU8(oid); // and again its PPS Object Id
685}
686
687bool
688POutPersist::serializeNullAndRepeat(PPersist const* x)
689{
690 if (x == NULL) {
691 PutRawUByte(PPS_NULL);
692 return true;
693 }
694
695 int_8 pos;
696 uint_8 id = findObjectId(x, pos);
697 if (id > 0) {
698 PutRawUByte(PPS_REFERENCE);
699 PutRawU8(id); // Writing the corresponding object Id
700 PutRawI8(pos); // The original object position
701 _nbrefs++; // Compteur de nombre de reference ecrits
702 return true;
703 }
704
705 return false; // Object have to be written in stream ...
706}
707
708uint_8
709POutPersist::assignObjectId(PPersist const* x)
710{
711 pps_OId += 16; // We keep the three first bytes for future usage
712 // Bit 1 non zero -> Object can be referenced
713 uint_8 id = pps_OId;
714 uint_8 mid = x->getMemOId();
715 if (mid > 0) {
716 int_8 pos;
717 if (findObjectId(x,pos) > 0)
718 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
719 id += 1; // Bit 1 non zero -> Object can be referenced
720 objreftag rt;
721 rt.ppsoid = id;
722 // cout << " DBG-rt.ppspos = s->tellp(); " << endl;
723 rt.ppspos = s->tellp();
724 // cout << " DBG-rt.ppspos = s->tellp(); = " << rt.ppspos << endl;
725 objList[mid] = rt;
726 }
727 return id;
728}
729
730uint_8
731POutPersist::findObjectId(PPersist const* x, int_8 & pos)
732{
733 pos = -1;
734 uint_8 mid = x->getMemOId();
735 if (mid == 0) return(0);
736 ObjList::iterator i = objList.find(mid);
737 if (i == objList.end()) return 0;
738 pos = (*i).second.ppspos;
739 return (*i).second.ppsoid;
740}
741
742
Note: See TracBrowser for help on using the repository browser.