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

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

MAJ commentaires pour documentation doxygen - Reza 9 Juin 2005

File size: 21.2 KB
RevLine 
[2615]1#include "sopnamsp.h"
[241]2#include "machdefs.h"
[251]3#include <stdio.h>
4#include <sys/types.h>
5#include <time.h>
[241]6#include "pexceptions.h"
[219]7#include "ppersist.h"
[802]8#include "anydataobj.h"
[2322]9#include <iostream>
[2657]10#include <iomanip>
[241]11#include <typeinfo>
[219]12
[2475]13// ------------------------- Historique ---------------------------
14// Le code de ppersist a ete separe en deux en Decembre 2003
15// a partir de la version CVS (1.26 - ppersist.cc) et
16// (1.19 - ppersist.h) .
17// la partie sur l'ecriture des donnees de base et leurs tableaux
18// a ete mis dans les fichiers ppfbinstream.h .cc
19// (Classes PPFBinaryInputStream et PPFBinaryOutputStream
20// -----------------------------------------------------------------
[219]21
22
[241]23
[2805]24/*!
25 \class SOPHYA::PIOPersist
26 \ingroup BaseTools
27 Handles (statically) the registration of PPF Sophya Persistence) handler classes.
28 \sa PPersist
29*/
30
31
[219]32//++
[241]33// Class PIOPersist
[219]34// Lib Outils++
35// include ppersist.h
36//
[241]37// Root class for persistant files. Handles the registration of
38// persistant classes
[219]39//--
40
[742]41MD5_CONTEXT PIOPersist::ctx;
[802]42PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
43map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
44map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
[241]45
[269]46//++
47void
48PIOPersist::Initialize()
49// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
50//--
51{
[802]52ppclassList = new PIOPersist::ClassList;
53ppclassNameList = new map<string, uint_8>;
54dobjclassNameList = new map<string, uint_8>;
[1900]55cout << " PIOPersist::Initialize() Starting Sophya Persistence management service " << endl;
[269]56}
[241]57
[2805]58/*!
59 Register a new persistence handler (PPersist) class.
60 The classId is usually a hash of the class< name, and
61 ppclass_name is typeid(PPersistClass).name() .
62 This method is called only through the PPersistRegistrar template
63*/
[219]64void
[802]65PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
[219]66{
[802]67 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
68 cerr << "RegisterClass : Error, " << hex << classId << dec
69 << " already registered." << endl;
[816]70 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
[802]71 }
72 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
73 cerr << "RegisterClass : Error (2) " << ppclass_name
74 << " already registered." << endl;
[816]75 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
[219]76 }
77
[802]78 (*ppclassList)[classId] = f;
79 (*ppclassNameList)[ppclass_name] = classId;
[219]80}
81
[2805]82/*!
83 Register a new DataObj class corresponding to a PPersist classId
84 class_typename should be typeid(DataObject).name()
85*/
[802]86void
87PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
88{
[816]89 if (ppclassList->find(classId) == ppclassList->end() ) {
90 cerr << "PIOPersist::RegisterDataObjClass() Error (1) "
91 << hex << classId << dec << " Not Found !" << endl;
92 throw( NotFoundExc("PIOPersist::RegisterDataObjClass() Not found classId ") );
93 }
94 if (dobjclassNameList->size() && (dobjclassNameList->find(class_name) != dobjclassNameList->end())) {
95 cerr << "PIOPersist::RegisterDataObjClass() Error (2)" << class_name
96 << " already registered." << endl;
97 throw(DuplicateIdExc("PIOPersist::RegisterDataObjClass() - Already registered"));
98 }
[219]99
[802]100 (*dobjclassNameList)[class_name] = classId;
101}
102
103// class_typename should be typeid(DataObject).name(), to be
104// used by POutPersist::PutDataObject() methods.
105
[2657]106//! Lists the registered PPersist handler classes and the corresponding class id.
107void
108PIOPersist::ListPPHandlers()
109{
110 cout << " PIOPersist::ListPPHandlers() - List of registered PPersist handler classes " << endl;
111 map<string, uint_8>::iterator it;
112 int k = 0;
113 for (it = (*ppclassNameList).begin(); it != (*ppclassNameList).end(); it++) {
114 cout << ++k << ": " << (*it).first << "\n" << " ClassId: Hex= "
115 << hex << (*it).second << " (Dec= " << dec << (*it).second << ")" << endl;
116 }
117}
118
119//! Lists the registered DataObj classes with the corresponding PPHandler name
120void
121PIOPersist::ListDataObjClasses()
122{
123 cout << " PIOPersist::ListDataObjClasses() : Registered DataObj class list " << endl;
124 map<string, uint_8>::iterator it;
125 int k = 0;
126 for (it = (*dobjclassNameList).begin(); it != (*dobjclassNameList).end(); it++) {
127 cout << ++k << "- " << (*it).first << " -> " << getPPClassName((*it).second) << endl;
128 }
129}
130
[2805]131//! Returns the PPersist class creator function for the specified classId
[241]132PIOPersist::ClassCreatorFunc
133PIOPersist::FindCreatorFunc(uint_8 classId)
[219]134{
[802]135 ClassList::iterator i = ppclassList->find(classId);
136 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
[241]137 return (*i).second;
[219]138}
139
[2805]140//! Returns the PPersist class name for the specified classId
[802]141string
142PIOPersist::getPPClassName(uint_8 classId)
143{
144 map<string, uint_8>::iterator i;
145 for (i= ppclassNameList->begin(); i != ppclassNameList->end(); i++)
146 if ( (*i).second == classId ) return (*i).first;
[219]147
[802]148 throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
149}
150
[2805]151//! Returns the classId for the specified PPersist class type name
[802]152uint_8
153PIOPersist::getPPClassId(string const & typ_name)
154{
155 map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
156 if (i == ppclassNameList->end())
157 throw(NotFoundExc("PIOPersist::getPPClassId() Not found className"));
158 return (*i).second;
159}
160
[2805]161//! Returns the classId for the specified PPersist class
[802]162uint_8
163PIOPersist::getPPClassId(PPersist const & ppo)
164{
165 string typ_name = typeid(ppo).name() ;
166 return (getPPClassId(typ_name) );
167}
168
169
[2805]170//! Returns the PPersist class name for the specified classId
[802]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
[2805]181//! Returns the classId for the specified PPersist class type name
[802]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
[2805]191//! Returns the classId for the specified PPersist class
[802]192uint_8
193PIOPersist::getDataObjClassId(AnyDataObj const & o)
194{
195 string typ_name = typeid(o).name() ;
196 return (getDataObjClassId(typ_name) );
197}
198
[2805]199//! \cond
[2476]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}
[802]212
[2805]213//! \endcond
[1202]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
[2476]222 bswap8_hash(&hash1);
223 bswap8_hash(&hash2);
[1202]224#endif
225
226 return (hash1+hash2);
227}
228
229
[219]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
[2805]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
[219]263void
264PPersist::Write(string const& fn) const
265{
266 POutPersist of(fn);
267 Write(of);
268}
269
[2805]270//! Reads the object from a PInPersist stream created from file \b fn
[219]271void
272PPersist::Read(string const& fn)
273{
274 PInPersist inf(fn);
[2698]275 inf.SkipToNextObject();
[219]276 Read(inf);
277}
278
[2805]279//! Writes the object to the output PPF stream \b s
[219]280void
281PPersist::Write(POutPersist& s) const
282{
[802]283 s.PutPPObject(this);
[219]284}
285
286
[2805]287//! Reads the object from the input PPF stream \b s
[219]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
[241]293// objet, utiliser PInPersist::ReadObject.
294// Il faut qu'on soit un objet ecrit
[219]295//--
296{
[241]297 // We should be the exact type
298 // Check tag value
[802]299 unsigned char ppstype,ppstag;
[588]300 s.GetTypeTag(ppstype);
[802]301 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
[241]302 }
[802]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)
[241]320 }
[802]321 else if ( ppstype == PInPersist::PPS_REFERENCE )
322 s.ReadReference(*this);
[219]323
[802]324 else throw FileFormatExc("PPersist::Read() : not an object in flow");
325
[219]326}
327
[2805]328//! Writes a name tag (\b tag) and then the object to the output PPF stream \b s
[241]329void
330PPersist::Write(POutPersist& s, string const& tag) const
[219]331{
[2441]332 s.WriteNameTag(tag);
[802]333 s.PutPPObject(this);
[219]334}
335
[2805]336//! Try to position at the name tag \b tag and then reads the object from the input stream \b s
[219]337void
[241]338PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]339{
[2459]340 if (!s.GotoNameTag(tag))
[241]341 throw NotFoundExc("PPersist::ReadAtTag tag not found");
342 Read(s);
[219]343}
344
[802]345// Renvoie l'identificateur de l'objet - par defaut=0
[2805]346/*! Return the object identifier (default: return 0)
347 (used for handling of PPF I/O for objects with reference sharing).
348*/
[802]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()
[2805]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*/
[802]361void
362PPersist::ShareDataReference(PPersist & pcs)
363{
364 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
365}
366
[2805]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*/
[802]371PPersist *
372PPersist::CloneSharedReference()
373{
374 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
375}
376
[219]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
[2805]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*/
[2482]411PInPersist::PInPersist(RawInOutStream * is, bool ad, bool scan)
412 : PPFBinaryInputStream(is, ad, scan)
413{
414}
415
[2805]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*/
[219]420PInPersist::PInPersist(string const& flnm, bool scan)
[2475]421 : PPFBinaryInputStream(flnm, scan)
[219]422{
423}
424
425
426
427PInPersist::~PInPersist()
428{
[802]429 ObjList::iterator i;
430 for(i=objList.begin(); i!= objList.end(); i++)
431 if ((*i).second) delete (*i).second;
[219]432}
433
434
[802]435
[582]436string
[802]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
[2805]448/*! Skip to next object in the streams, reads it and return
449 the corresponding PPersist handler
450*/
[241]451PPersist*
452PInPersist::ReadObject()
453{
[2698]454 SkipToNextObject();
[802]455 return(GetPPObject());
456}
457
[2805]458/*!
459 Tries to read in from the stream into object \b o
460*/
[802]461void
462PInPersist::GetObject(AnyDataObj & o)
463{
464 GetPPObject(&o);
465 return;
466}
467
[2805]468/*!
469 Tries to move to \b nametag and then read in from the stream into object \b o
470*/
[802]471void
472PInPersist::GetObject(AnyDataObj & o, string tagname)
473{
[2459]474 GotoNameTag(tagname);
[802]475 GetPPObject(&o);
476 return;
477}
478
[2805]479/*!
480 Reading of objects - used by GetObject() and ReadObject()
481*/
[802]482PPersist*
483PInPersist::GetPPObject(AnyDataObj * po)
484{
[241]485 // Get tag
[802]486 unsigned char ppstype;
[588]487 GetTypeTag(ppstype);
[241]488 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]489 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]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);
[802]498 uint_8 oid,oid2;
499 GetRawU8(oid);
[241]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();
[802]509 // If a DataObject was specified , we assign it to the PPersistObject
510 if (po != NULL) object->SetDataObj(*po);
511
[241]512 object->ReadSelf(*this);
[802]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);
[241]523 return object;
[802]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)
[241]535{
[802]536 PPersist * pr = ReadReference();
537 ppo.ShareDataReference(*pr);
[241]538}
539
[802]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()) ) {
[2459]575 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
[802]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
[219]590//++
591// Class POutPersist
592// Lib Outils++
593// include ppersist.h
594//
595// Fichier d'objets persistants, en écriture.
596//--
597
598
[2805]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
[219]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//--
[2805]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*/
[2477]621POutPersist::POutPersist(RawInOutStream* os, bool ad, int endianness)
622 : PPFBinaryOutputStream(os, ad, endianness)
623{
624 pps_OId = 0;
625 wobj_level = 0;
626}
627
[2805]628/*! Constructor
629 \param flnm : output file name
630 \param endianness : Endianness selector PPS_NATIVE PPS_LITTLE_ENDIAN PPS_BIG_ENDIAN
631*/
[219]632POutPersist::POutPersist(string const& flnm, int endianness)
[2475]633 : PPFBinaryOutputStream(flnm, endianness)
[219]634{
[802]635 // PPS (POutPersist stream) Object Id initialisation
636 pps_OId = 0;
[2477]637 wobj_level = 0;
[219]638}
639
640POutPersist::~POutPersist()
641{
642}
643
644
[2805]645//! Writes the object \b o to the stream
[241]646void
[802]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);
[219]655}
656
[2805]657//! Writes the nametag \b tagname and then the object \b o to the stream
[241]658void
[802]659POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]660{
[2441]661 WriteNameTag(tagname);
[802]662 PutObject(o);
663}
[219]664
[802]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
[2477]674 wobj_level++; // Niveau d'imbrication d'ecriture d'objets
[802]675 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
676 PutRawU8(oid); // Write the PPS Object Id
[241]677 obj->WriteSelf(*this);
[2477]678 // Comptage d'objets ecrits
679 _nbobjs++;
[2482]680 if (wobj_level > _maxnestlevel) _maxnestlevel = wobj_level;
[2477]681 if (wobj_level == 1) _nbtlobjs++;
682 wobj_level--;
[802]683 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
684 PutRawU8(oid); // and again its PPS Object Id
[241]685}
[219]686
[241]687bool
688POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]689{
[241]690 if (x == NULL) {
[802]691 PutRawUByte(PPS_NULL);
[241]692 return true;
693 }
[219]694
[802]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
[2482]701 _nbrefs++; // Compteur de nombre de reference ecrits
[241]702 return true;
703 }
[219]704
[802]705 return false; // Object have to be written in stream ...
[219]706}
707
[802]708uint_8
[241]709POutPersist::assignObjectId(PPersist const* x)
[219]710{
[802]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 ! ");
[821]719 id += 1; // Bit 1 non zero -> Object can be referenced
[802]720 objreftag rt;
721 rt.ppsoid = id;
[2476]722 // cout << " DBG-rt.ppspos = s->tellp(); " << endl;
[802]723 rt.ppspos = s->tellp();
[2476]724 // cout << " DBG-rt.ppspos = s->tellp(); = " << rt.ppspos << endl;
[802]725 objList[mid] = rt;
726 }
[241]727 return id;
[219]728}
729
[802]730uint_8
731POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]732{
[802]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;
[219]740}
741
[241]742
Note: See TracBrowser for help on using the repository browser.