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

Last change on this file since 2434 was 2430, checked in by ansari, 22 years ago

Portage sous MacOSX 10.2 - g++ 3.1 (Pb avec classe SophyaInitiator statique, lecture last byte ds istream) , Reza 12/09/2003

File size: 41.9 KB
RevLine 
[241]1#include "machdefs.h"
[251]2#include <stdio.h>
3#include <sys/types.h>
4#include <time.h>
[241]5#include "pexceptions.h"
[219]6#include "ppersist.h"
[802]7#include "anydataobj.h"
[2322]8#include <fstream>
9#include <iostream>
[241]10#include <typeinfo>
[219]11
12
13#ifdef __mac__
14#include "unixmac.h"
15#include <SIOUX.h>
16#endif
17
[802]18// strptime n'est pas defini sous Linux - Reza Mars 2000
[1783]19#if defined(OS_LINUX) || defined(OS_MACOSX)
[802]20extern "C" {
[2111]21char *strptime(const char *buf, const char *format, struct tm *tm);
[802]22}
23#endif
24
[241]25#define MAXTAGLEN 255
26
[219]27//++
[241]28// Class PIOPersist
[219]29// Lib Outils++
30// include ppersist.h
31//
[241]32// Root class for persistant files. Handles the registration of
33// persistant classes
[219]34//--
35
36//++
[241]37// Links See
[219]38// PPersist
[241]39// PInPersist
40// POutPersist
[219]41//--
42
43
[742]44MD5_CONTEXT PIOPersist::ctx;
[802]45PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
46map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
47map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
[241]48
[269]49//++
50void
51PIOPersist::Initialize()
52// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
53//--
54{
[802]55ppclassList = new PIOPersist::ClassList;
56ppclassNameList = new map<string, uint_8>;
57dobjclassNameList = new map<string, uint_8>;
[1900]58cout << " PIOPersist::Initialize() Starting Sophya Persistence management service " << endl;
[269]59}
[241]60
[219]61//++
62void
[802]63PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
[219]64//
[802]65// Register a new persistence handler (PPersist) class.
66// The classId is usually a hash of the class name, and
67// ppclass_name is typeid(PPersistClass).name() .
68// This method is called only through the PPersistRegistrar template
[219]69//
70//--
71{
[802]72 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
73 cerr << "RegisterClass : Error, " << hex << classId << dec
74 << " already registered." << endl;
[816]75 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
[802]76 }
77 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
78 cerr << "RegisterClass : Error (2) " << ppclass_name
79 << " already registered." << endl;
[816]80 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
[219]81 }
82
[802]83 (*ppclassList)[classId] = f;
84 (*ppclassNameList)[ppclass_name] = classId;
[219]85}
86
[802]87//++
88void
89PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
90// Register a new DataObj class corresponding to a PPersist classId
91// class_typename should be typeid(DataObject).name()
92//--
93{
[816]94 if (ppclassList->find(classId) == ppclassList->end() ) {
95 cerr << "PIOPersist::RegisterDataObjClass() Error (1) "
96 << hex << classId << dec << " Not Found !" << endl;
97 throw( NotFoundExc("PIOPersist::RegisterDataObjClass() Not found classId ") );
98 }
99 if (dobjclassNameList->size() && (dobjclassNameList->find(class_name) != dobjclassNameList->end())) {
100 cerr << "PIOPersist::RegisterDataObjClass() Error (2)" << class_name
101 << " already registered." << endl;
102 throw(DuplicateIdExc("PIOPersist::RegisterDataObjClass() - Already registered"));
103 }
[219]104
[802]105 (*dobjclassNameList)[class_name] = classId;
106}
107
108// class_typename should be typeid(DataObject).name(), to be
109// used by POutPersist::PutDataObject() methods.
110
[241]111PIOPersist::ClassCreatorFunc
112PIOPersist::FindCreatorFunc(uint_8 classId)
[802]113// Returns the PPersist class creator function for the specified classId
[219]114{
[802]115 ClassList::iterator i = ppclassList->find(classId);
116 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
[241]117 return (*i).second;
[219]118}
119
[802]120string
121PIOPersist::getPPClassName(uint_8 classId)
122// Returns the PPersist class name for the specified classId
123{
124 map<string, uint_8>::iterator i;
125 for (i= ppclassNameList->begin(); i != ppclassNameList->end(); i++)
126 if ( (*i).second == classId ) return (*i).first;
[219]127
[802]128 throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
129}
130
131uint_8
132PIOPersist::getPPClassId(string const & typ_name)
133// Returns the classId for the specified PPersist class type name
134{
135 map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
136 if (i == ppclassNameList->end())
137 throw(NotFoundExc("PIOPersist::getPPClassId() Not found className"));
138 return (*i).second;
139}
140
141uint_8
142PIOPersist::getPPClassId(PPersist const & ppo)
143// Returns the classId for the specified PPersist class
144{
145 string typ_name = typeid(ppo).name() ;
146 return (getPPClassId(typ_name) );
147}
148
149
150string
151PIOPersist::getDataObjClassName(uint_8 classId)
152// Returns the PPersist class name for the specified classId
153{
154 map<string, uint_8>::iterator i;
155 for (i= dobjclassNameList->begin(); i != dobjclassNameList->end(); i++)
156 if ( (*i).second == classId ) return (*i).first;
157
158 throw(NotFoundExc("PIOPersist::getDataObjClassName() Not found classId"));
159}
160
161uint_8
162PIOPersist::getDataObjClassId(string const & typ_name)
163// Returns the classId for the specified PPersist class type name
164{
165 map<string, uint_8>::iterator i = dobjclassNameList->find(typ_name);
166 if (i == dobjclassNameList->end())
167 throw(NotFoundExc("PIOPersist::getDataObjClassId() Not found className"));
168 return (*i).second;
169}
170
171uint_8
172PIOPersist::getDataObjClassId(AnyDataObj const & o)
173// Returns the classId for the specified PPersist class
174{
175 string typ_name = typeid(o).name() ;
176 return (getDataObjClassId(typ_name) );
177}
178
179
[1202]180static inline void bswap8(void* p)
181{
182 uint_8 tmp = *(uint_8*)p;
183 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
184 ((tmp >> (5*8)) & 0x0000FF00) |
185 ((tmp >> (3*8)) & 0x00FF0000) |
186 ((tmp >> (1*8)) & 0xFF000000) |
187 ((tmp & 0xFF000000) << (1*8)) |
188 ((tmp & 0x00FF0000) << (3*8)) |
189 ((tmp & 0x0000FF00) << (5*8)) |
190 ((tmp & 0x000000FF) << (7*8));
191}
192
193static inline void bswap4(void* p)
194{
195 uint_4 tmp = *(uint_4*)p;
196 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
197 ((tmp >> 8) & 0x0000FF00) |
198 ((tmp & 0x0000FF00) << 8) |
199 ((tmp & 0x000000FF) << 24);
200}
201
202static inline void bswap2(void* p)
203{
204 uint_2 tmp = *(uint_2*)p;
205 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
206 ((tmp & 0x00FF) << 8);
207}
208
209
210uint_8 PIOPersist::Hash(string const& typname) {
211 md5_init(&ctx);
212 md5_write(&ctx, (unsigned char*) typname.c_str(), typname.size());
213 md5_final(&ctx);
214 uint_8 hash1 = *((uint_8*) ctx.buf);
215 uint_8 hash2 = *((uint_8*) (ctx.buf+8));
216#if IS_BIG_ENDIAN
217 bswap8(&hash1);
218 bswap8(&hash2);
219#endif
220
221 return (hash1+hash2);
222}
223
224
[219]225//++
226// Class PPersist
227// Lib Outils++
228// include ppersist.h
229//
230// Classe de base pour des objets persistants. Pour créer un objet
231// persistant :
232// - Hériter de PPersist.
233// - Définir un numéro d'identification de la classe, unique dans Peida
234// - Implémenter "ClassId()"
235// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
236// membres que l'on souhaite écrire, et les relire dans le même ordre.
237// Pour écrire une référence à un objet : l'objet doit être un PPersist,
238// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
239// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
240// fois, il faut que cet objet soit un PShPersist.
241// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
242// les fonctions PutXX/GetXX de PInPersist/POutPersist.
243//
244// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
245// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
246//--
247
248//++
[241]249// Links See
[219]250// PInPersist
251// POutPersist
[241]252// PIOPersist
[219]253//--
254
255//++
256void
257PPersist::Write(string const& fn) const
258//
259// Ecrit l'objet dans un nouveau fichier ppersist "fn".
260//--
261{
262 POutPersist of(fn);
263 Write(of);
264}
265
266//++
267void
268PPersist::Read(string const& fn)
269//
270// Relit l'objet dans le fichier ppersist "fn". Il faut connaître a priori
271// le type de l'objet. Pour une relecture avec création automatique du bon
272// objet, utiliser PPersistMgr::ReadObject.
273//--
274{
275 PInPersist inf(fn);
276 Read(inf);
277}
278
279//++
280void
281PPersist::Write(POutPersist& s) const
282//
283// Ecrit l'objet dans le fichier PPersist.
284//--
285{
[802]286 s.PutPPObject(this);
[219]287}
288
289
290//++
291void
292PPersist::Read(PInPersist& s)
293//
294// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
295// le type de l'objet. Pour une relecture avec création automatique du bon
[241]296// objet, utiliser PInPersist::ReadObject.
297// Il faut qu'on soit un objet ecrit
[219]298//--
299{
[241]300 // We should be the exact type
301 // Check tag value
[802]302 unsigned char ppstype,ppstag;
[588]303 s.GetTypeTag(ppstype);
[802]304 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
[241]305 }
[802]306 if (ppstype == PInPersist::PPS_OBJECT) {
307 // Check class id
308 uint_8 classId;
309 s.GetRawU8(classId);
310 uint_8 oid,oid2;
311 s.GetRawU8(oid);
312 if (classId != PIOPersist::getPPClassId(*this) )
313 throw FileFormatExc("PPersist::Read (): not the same object type");
314 ReadSelf(s);
315 // Read the ENDOBJECT
316 s.GetRawUByte(ppstag);
317 if (ppstag != PInPersist::PPS_ENDOBJECT)
318 throw FileFormatExc("PPersist::Read() No PPS_ENDOBJECT tag");
319 s.GetRawU8(oid2);
320 if (oid2 != oid)
321 throw FileFormatExc("PPersist::Read() Inconsistent PPS-OId at PPS_ENDOBJECT ");
322 s.KeepOId(oid, *this); // Object should be kept with its PPS_OId (if oid > 0)
[241]323 }
[802]324 else if ( ppstype == PInPersist::PPS_REFERENCE )
325 s.ReadReference(*this);
[219]326
[802]327 else throw FileFormatExc("PPersist::Read() : not an object in flow");
328
[219]329}
330
331//++
[241]332void
333PPersist::Write(POutPersist& s, string const& tag) const
[219]334//
[241]335// Ecrit l'objet dans le fichier PPersist avec un tag
[219]336//--
337{
[241]338 s.WriteTag(tag);
[802]339 s.PutPPObject(this);
[219]340}
341
342//++
343void
[241]344PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]345//
346// Lit l'objet à la position du tag numéro "tagid".
347//--
348{
[241]349 if (!s.GotoTag(tag))
350 throw NotFoundExc("PPersist::ReadAtTag tag not found");
351 Read(s);
[219]352}
353
[802]354// Renvoie l'identificateur de l'objet - par defaut=0
[219]355
[802]356uint_8
357PPersist::getMemOId() const
358{
359 return(0);
360}
361
362// Ces deux methodes doivent etre redefinies si getMemOId() renvoie non nul (>0)
363// ShareDataReference() et CloneSharedReference()
364void
365PPersist::ShareDataReference(PPersist & pcs)
366{
367 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
368}
369
370PPersist *
371PPersist::CloneSharedReference()
372{
373 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
374}
375
[219]376//++
377// virtual void PPersist::ReadSelf(PInPersist&)=0
378// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
379// et PPersistMgr::ReadObject. Il faut relire les variables membres,
380// dans l'ordre où elles ont été écrites par WriteSelf.
381// virtual void PPersist::WriteSelf(POutPersist&) const=0
382// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
383// Il faut écrire les variables membres,
384// dans l'ordre où elles seront relues par ReadSelf.
385//--
386
387
388
389//++
390// Class PInPersist
391// Lib Outils++
392// include ppersist.h
393//
394// Fichier d'objets persistants, en lecture.
395//--
396
397//++
398PInPersist::PInPersist(string const& flnm, bool scan)
399//
400// Constructeur. Ouvre le fichier.
401//--
402{
[241]403 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
404
405 // Read and check header
406
[219]407 char rbuf[36];
[241]408 GetRawBytes(rbuf, 32);
[576]409 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
[241]410 throw FileFormatExc("PInPersist::PInPersist bad header");
[219]411 }
[802]412 rbuf[32] = '\0';
413 version = atoi(rbuf+25);
414 if (version < 2) {
415 cerr << "PInPersist::PInPersist(" << flnm << ") Version(=" << version
416 << ") < 2 not supported !" << endl;
417 throw FileFormatExc("PInPersist::PInPersist() - Unsupported (Old) Version");
418 }
[241]419 // read endianness
420 GetRawBytes(rbuf, 32);
421 if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
422 bigEndian = true;
423 else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
424 bigEndian = false;
425 else {
426 throw FileFormatExc("PInPersist::PInPersist bad header - endianness");
427 }
428
429 // read creation date
430 GetRawBytes(rbuf, 32);
431 rbuf[32] = '\0';
432 struct tm tm;
[1783]433 #if !(defined(__MWERKS__) || defined(OS_MACOSX))
[742]434 strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
435 #else
436 sscanf(rbuf,"%2d/%2d/%4d %2d:%2d:%2d GMT",&tm.tm_mday,&tm.tm_mon,&tm.tm_year,
437 &tm.tm_hour,&tm.tm_min,&tm.tm_sec);
438 tm.tm_mon --;
439 tm.tm_year -= 1900;
440 #endif
[241]441 creationdate = mktime(&tm);
[802]442 filename = flnm; // keep the filename
443 seqread = true; // To flag non sequential reads
[241]444 if (scan) Scan();
[219]445}
446
447
448
449PInPersist::~PInPersist()
450{
[802]451 ObjList::iterator i;
452 for(i=objList.begin(); i!= objList.end(); i++)
453 if ((*i).second) delete (*i).second;
[219]454 delete s;
455}
456
457
[802]458string
459PInPersist::CreationDateStr()
460{
461 time_t cdt = CreationDate();
462 string cdate = ctime(&cdt);
463 return(cdate);
464}
465
[219]466void
467PInPersist::Scan()
468{
[241]469 // On cherche la liste des tags, a la fin du fichier
[219]470
[802]471 unsigned char ppstype;
[241]472 size_t debut;
473#ifdef STREAMPOS_IS_CLASS
[219]474 debut = s->tellg().offset();
[241]475#else
[219]476 debut = s->tellg();
[241]477#endif
[219]478
[241]479 // Find tag entries at end of file
[2430]480 // if (defined(Linux) || defined(Darwin)) && defined(__GNUG__) && (__GNUC__ < 3)
481#if defined(__GNUG__) && (__GNUC__ < 3)
[1101]482 // There seems to be a bug where seekg with ios::end under Linux with g++
[2430]483 // prior to version gcc 3.1
484 // The bug seems to be there also with Darwin/MacOSX
[1063]485 // So, we use seek with ios::beg
486 s->seekg(0, ios::end);
487 int_8 tagpos = s->tellg() - (sizeof(int_8)+1);
488 s->seekg(tagpos, ios::beg);
[1101]489#else
490 s->seekg(-(sizeof(int_8)+1), ios::end);
[1063]491#endif
492
[588]493 GetTypeTag(ppstype);
[241]494 if (ppstype != PPS_EOF)
495 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
[219]496
[241]497 int_8 pos;
498 GetRawI8(pos);
[2430]499#if defined(Darwin)
500 // Septembre 2003 - Reza : Pb avec MacOSX 10.2
501 // Sur MacOSX (10.2, g++ 3.1), la lecture du dernier byte du flot cause
502 // une erreur, et le flot ne se repositionne plus
503 // On ferme le flot et on le rouvre ...
504 delete s;
505 s = new ifstream(FileName().c_str(), ios::in | IOS_BIN);
506#endif
[241]507 if (pos < 0) { // no tags
508 s->seekg(debut);
509 return;
510 }
[219]511
[241]512 char buffer[MAXTAGLEN+1];
513 s->seekg(pos);
514 while (true) {
[588]515 GetTypeTag(ppstype);
[241]516 if (ppstype == PPS_EOF) break;
517
518 if (ppstype != PPS_TAG)
519 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
[219]520
[241]521 GetRawI8(pos);
522 int_4 len;
523 GetRawI4(len);
524 if (len > MAXTAGLEN)
525 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
526 GetRawBytes(buffer, len);
527 buffer[len] = '\0';
[219]528
[241]529 tags[buffer] = pos;
[219]530 }
[241]531 s->seekg(debut);
[219]532}
533
534
[256]535int
536PInPersist::NbTags()
537{
538 return tags.size();
539}
540
[219]541bool
[241]542PInPersist::GotoTag(string const& name)
[219]543{
[241]544 map<string, int_8>::iterator i = tags.find(name);
545 if (i == tags.end())
546 return false;
547 // throw NotFoundExc("PInPersist::GotoTag tag not found");
548 s->seekg((*i).second);
[802]549 seqread = false;
550 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[219]551 return(true);
552}
553
[256]554bool
555PInPersist::GotoTagNum(int itag)
556{
[582]557 if (itag<0 || itag >= (int)tags.size()) return false;
[256]558 map<string, int_8>::iterator i = tags.begin();
559 for (int j=0; j<itag; j++) i++;
560 s->seekg((*i).second);
[871]561 seqread = false;
[802]562 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[256]563 return(true);
564}
565
[582]566string
567PInPersist::GetTagName(int itag)
568{
569 if (itag<0 || itag >= (int)tags.size()) return "";
570 map<string, int_8>::iterator i = tags.begin();
571 for (int j=0; j<itag; j++) i++;
572 return((*i).first);
573}
[256]574
[802]575string
576PInPersist::GetTagClassName(int itag)
577{
578 // A faire
579// if (itag<0 || itag >= (int)tags.size()) return "";
580// map<string, int_8>::iterator i = tags.begin();
581// for (int j=0; j<itag; j++) i++;
582// uint_8 cid = (*i).second;
583// return(GetClassName(cid));
584 return("");
585}
586
[582]587static vector<string> * ret_tag_names = NULL;
588vector<string> const &
589PInPersist::GetTagNames()
590{
591if (ret_tag_names) delete ret_tag_names;
592ret_tag_names = new vector<string> ;
593map<string, int_8>::iterator i;
594for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
595return(*ret_tag_names);
596}
597
[219]598//++
599// void PInPersist::GetByte(char& c)
600// void PInPersist::GetBytes(void* ptr, size_t bytes)
601// void PInPersist::GetR4 (r_4& result)
602// void PInPersist::GetR4s (r_4* tab, size_t n)
603// void PInPersist::GetR8 (r_8& result)
604// void PInPersist::GetR8s (r_8* tab, size_t n)
605// void PInPersist::GetI2 (int_2& result)
606// void PInPersist::GetI2s (int_2* tab, size_t n)
607// void PInPersist::GetU2 (uint_2& result)
608// void PInPersist::GetU2s (uint_2* tab, size_t n)
609// void PInPersist::GetI4 (int_4& result)
610// void PInPersist::GetI4s (int_4* tab, size_t n)
611// void PInPersist::GetU4 (uint_4& result)
612// void PInPersist::GetU4s (uint_4* tab, size_t n)
613// void PInPersist::GetI8 (int_8& result)
614// void PInPersist::GetI8s (int_8* tab, size_t n)
615// void PInPersist::GetU8 (uint_8& result)
616// void PInPersist::GetU8s (uint_8* tab, size_t n)
617// Lecture de données portables depuis le fichier PPersist. Pour chaque type
618// de données, on peut lire une valeur, ou un tableau de valeurs.
619// void PInPersist::GetLine(char* ptr, size_t len)
620// Lecture d'une ligne de texte depuis le fichier PPersist.
621//--
622
623
[588]624void
[802]625PInPersist::GetTypeTag(unsigned char& c)
[588]626{
[802]627 c = PPS_TAG_MARK;
628 while (c == PPS_TAG_MARK) GetRawUByte(c);
629 // while (c == PPS_TAG_MARK) { Il ne faut plus faire ca !
630 // objList.clear(); $CHECK$ Reza 03/2000
631 // GetRawByte(c);
632 // }
[588]633}
[241]634
[588]635
[219]636void
[241]637PInPersist::GetRawByte(char& c)
638{
639 GetRawBytes(&c, 1);
640}
641
642void
[802]643PInPersist::GetRawUByte(unsigned char& c)
644{
645 GetRawBytes(&c, 1);
646}
647
648void
[241]649PInPersist::GetRawBytes(void* ptr, size_t bytes)
650{
651 s->read((char*)ptr, bytes);
652}
653
654void
655PInPersist::GetRawI2 (int_2& result)
656{
657 GetRawBytes(&result, sizeof(int_2));
658 if (bigEndian != IS_BIG_ENDIAN)
659 bswap2(&result);
660}
661
662void
663PInPersist::GetRawI4 (int_4& result)
664{
665 GetRawBytes(&result, sizeof(int_4));
666 if (bigEndian != IS_BIG_ENDIAN)
667 bswap4(&result);
668}
669
670void
671PInPersist::GetRawI8 (int_8& result)
672{
673 GetRawBytes(&result, sizeof(int_8));
674 if (bigEndian != IS_BIG_ENDIAN)
675 bswap8(&result);
676}
677
678void
679PInPersist::GetRawU8 (uint_8& result)
680{
681 GetRawBytes(&result, sizeof(uint_8));
682 if (bigEndian != IS_BIG_ENDIAN)
683 bswap8(&result);
684}
685
686void
[802]687PInPersist::CheckTag(short datasz, short datatype)
688// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]689{
[802]690 unsigned char ppstype;
[588]691 GetTypeTag(ppstype);
[802]692 if (ppstype != PPS_SIMPLE + datasz + datatype)
[256]693 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]694}
695
696void
[802]697PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
698// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]699{
[802]700 unsigned char ppstype;
[588]701 GetTypeTag(ppstype);
[241]702 size_t filesz;
[802]703 if (sz <= 0x7fffffff) {
704 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
705 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]706 int_4 ff;
707 GetRawI4(ff); filesz=ff;
708 } else {
[802]709 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
710 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]711 uint_8 ff;
712 GetRawU8(ff); filesz=ff;
713 }
714 if (filesz != sz)
[802]715 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
[241]716}
717
718void
719PInPersist::GetByte(char& c)
720{
[802]721 CheckTag(1,PPS_DATATYPE_CHAR);
[241]722 GetRawBytes(&c, 1);
723}
724
[802]725
[241]726void
727PInPersist::GetBytes(void* ptr, size_t bytes)
728{
[802]729 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]730 GetRawBytes(ptr, bytes);
731}
732void
[219]733PInPersist::GetR4 (r_4& result)
734{
[802]735 CheckTag(4,PPS_DATATYPE_FLOAT);
[241]736 GetRawBytes(&result, sizeof(r_4));
[219]737 if (bigEndian != IS_BIG_ENDIAN)
738 bswap4(&result);
739}
740
741
742void
743PInPersist::GetR4s (r_4* tab, size_t n)
744{
[802]745 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
[241]746 GetRawBytes(tab, n*sizeof(r_4));
[219]747 if (bigEndian == IS_BIG_ENDIAN) return;
748
749 for (unsigned int i=0; i<n; i++)
750 bswap4(tab+i);
751
752 return;
753}
754
755void
756PInPersist::GetR8 (r_8& result)
757{
[802]758 CheckTag(8,PPS_DATATYPE_FLOAT);
[241]759 GetRawBytes(&result, sizeof(r_8));
[219]760 if (bigEndian != IS_BIG_ENDIAN)
761 bswap8(&result);
762}
763
764void
765PInPersist::GetR8s (r_8* tab, size_t n)
766{
[802]767 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
[241]768 GetRawBytes(tab, n*sizeof(r_8));
[219]769 if (bigEndian == IS_BIG_ENDIAN) return;
770
771 for (unsigned int i=0; i<n; i++)
772 bswap8(tab+i);
773
774 return;
775}
776
777void
778PInPersist::GetI2 (int_2& result)
779{
[802]780 CheckTag(2,PPS_DATATYPE_INTEGER);
[241]781 GetRawBytes(&result, sizeof(int_2));
[219]782 if (bigEndian != IS_BIG_ENDIAN)
783 bswap2(&result);
784}
785
786void
787PInPersist::GetI2s (int_2* tab, size_t n)
788{
[802]789 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
[241]790 GetRawBytes(tab, n*sizeof(int_2));
[219]791 if (bigEndian == IS_BIG_ENDIAN) return;
792
793 for (unsigned int i=0; i<n; i++)
794 bswap2(tab+i);
795
796 return;
797}
798
799void
800PInPersist::GetU2 (uint_2& result)
801{
[802]802 CheckTag(2,PPS_DATATYPE_UNSIGNED);
[241]803 GetRawBytes(&result, sizeof(uint_2));
[219]804 if (bigEndian != IS_BIG_ENDIAN)
805 bswap2(&result);
806}
807
808void
809PInPersist::GetU2s (uint_2* tab, size_t n)
810{
[802]811 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
[241]812 GetRawBytes(tab, n*sizeof(uint_2));
[219]813 if (bigEndian == IS_BIG_ENDIAN) return;
814
815 for (unsigned int i=0; i<n; i++)
816 bswap2(tab+i);
817
818 return;
819}
820
821void
822PInPersist::GetI4 (int_4& result)
823{
[802]824 CheckTag(4,PPS_DATATYPE_INTEGER);
[241]825 GetRawBytes(&result, sizeof(int_4));
[219]826 if (bigEndian != IS_BIG_ENDIAN)
827 bswap4(&result);
828}
829
830void
831PInPersist::GetI4s (int_4* tab, size_t n)
832{
[802]833 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
[241]834 GetRawBytes(tab, n*sizeof(int_4));
[219]835 if (bigEndian == IS_BIG_ENDIAN) return;
836
837 for (unsigned int i=0; i<n; i++)
838 bswap4(tab+i);
839
840 return;
841}
842
843void
844PInPersist::GetU4 (uint_4& result)
845{
[802]846 CheckTag(4,PPS_DATATYPE_UNSIGNED);
[241]847 GetRawBytes(&result, sizeof(uint_4));
[219]848 if (bigEndian != IS_BIG_ENDIAN)
849 bswap4(&result);
850}
851
852void
853PInPersist::GetU4s (uint_4* tab, size_t n)
854{
[802]855 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
[241]856 GetRawBytes(tab, n*sizeof(uint_4));
[219]857 if (bigEndian == IS_BIG_ENDIAN) return;
858
859 for (unsigned int i=0; i<n; i++)
860 bswap4(tab+i);
861
862 return;
863}
864
865
866void
867PInPersist::GetI8 (int_8& result)
868{
[802]869 CheckTag(8,PPS_DATATYPE_INTEGER);
[241]870 GetRawBytes(&result, sizeof(int_8));
[219]871 if (bigEndian != IS_BIG_ENDIAN)
872 bswap8(&result);
873}
874
875void
876PInPersist::GetI8s (int_8* tab, size_t n)
877{
[802]878 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
[241]879 GetRawBytes(tab, n*sizeof(int_8));
[219]880 if (bigEndian == IS_BIG_ENDIAN) return;
881
882 for (unsigned int i=0; i<n; i++)
883 bswap8(tab+i);
884
885 return;
886}
887
888void
889PInPersist::GetU8 (uint_8& result)
890{
[802]891 CheckTag(8,PPS_DATATYPE_UNSIGNED);
[241]892 GetRawBytes(&result, sizeof(uint_8));
[219]893 if (bigEndian != IS_BIG_ENDIAN)
894 bswap8(&result);
895}
896
897void
898PInPersist::GetU8s (uint_8* tab, size_t n)
899{
[802]900 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
[241]901 GetRawBytes(tab, n*sizeof(uint_8));
[219]902 if (bigEndian == IS_BIG_ENDIAN) return;
903
904 for (unsigned int i=0; i<n; i++)
905 bswap8(tab+i);
906
907 return;
908}
909
910
911void
912PInPersist::GetLine(char* ptr, size_t len)
913{
[802]914 string str;
915 GetStr(str);
916 strncpy(ptr, str.c_str(), len);
917 ptr[len] = '\0';
[219]918}
919
[241]920void
921PInPersist::GetStr(string& str)
922{
[802]923 unsigned char ppstype;
[588]924 GetTypeTag(ppstype);
[241]925 if (ppstype != PPS_STRING)
[802]926 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
927 int_4 len;
928 GetRawI4(len);
[582]929 char * buff = new char[len+1];
[241]930 GetRawBytes(buff, len);
931 buff[len] = '\0';
932 str = buff;
933 delete[] buff;
934}
[219]935
[802]936
[241]937PPersist*
938PInPersist::ReadObject()
939{
[802]940 return(GetPPObject());
941}
942
943void
944PInPersist::GetObject(AnyDataObj & o)
945{
946 GetPPObject(&o);
947 return;
948}
949
950void
951PInPersist::GetObject(AnyDataObj & o, string tagname)
952{
953 GotoTag(tagname);
954 GetPPObject(&o);
955 return;
956}
957
958PPersist*
959PInPersist::GetPPObject(AnyDataObj * po)
960{
[241]961 // Get tag
[802]962 unsigned char ppstype;
[588]963 GetTypeTag(ppstype);
[241]964 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]965 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]966 }
967
968 if (ppstype == PPS_NULL) {
969 return NULL;
970 } else if (ppstype == PPS_OBJECT) {
971 // Get class id
972 uint_8 classId;
973 GetRawU8(classId);
[802]974 uint_8 oid,oid2;
975 GetRawU8(oid);
[241]976
977 // Get factory method
978 ClassCreatorFunc f = FindCreatorFunc(classId);
979 if (!f) {
980 throw NotFoundExc("PInPersist::ReadObject class not registered");
981 }
982
983 // Create object
984 PPersist* object = f();
[802]985 // If a DataObject was specified , we assign it to the PPersistObject
986 if (po != NULL) object->SetDataObj(*po);
987
[241]988 object->ReadSelf(*this);
[802]989 unsigned char ppstag;
990 // Read the ENDOBJECT
991 GetRawUByte(ppstag);
992 if (ppstag != PPS_ENDOBJECT)
993 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
994 GetRawU8(oid2);
995 if (oid2 != oid)
996 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
997
998 KeepOId(oid, *object);
[241]999 return object;
[802]1000 }
1001 else if (ppstype == PPS_REFERENCE)
1002 return ReadReference();
1003
1004 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
1005}
1006
1007
1008void
1009PInPersist::AnalyseTags(int lev)
1010{
1011 unsigned char ppstag=0;
1012 unsigned char ppst1,ppst2,ppst3;
1013 uint_8 cpos,fsize;
1014 uint_8 ui8,cid,oid;
1015 int_4 i4;
1016 int_8 i8;
1017 char * buff;
1018 string str;
1019
1020 cout << "\n ---------------------------------------------------------- " << endl;
1021 cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl;
1022
1023
1024#ifdef STREAMPOS_IS_CLASS
1025 cpos = s->tellg().offset();
1026#else
1027 cpos = s->tellg();
1028#endif
1029 s->seekg(0,ios::end);
1030#ifdef STREAMPOS_IS_CLASS
1031 fsize = s->tellg().offset();
1032#else
1033 fsize = s->tellg();
1034#endif
1035 s->seekg(cpos,ios::beg);
1036
1037 cout << " Version= " << Version() << " FileSize= " << fsize
1038 << " Creation Date= " << CreationDateStr() << endl;
1039
1040 uint_8 totntags = 0;
1041 bool eofok = false;
1042
1043 while ( (ppstag != PPS_EOF) && (cpos < fsize) ) {
1044#ifdef STREAMPOS_IS_CLASS
1045 cpos = s->tellg().offset();
1046#else
1047 cpos = s->tellg();
1048#endif
1049 GetRawUByte(ppstag);
1050 totntags++;
1051
1052 ppst1 = ppstag&0x0f; // bits 0123
1053 ppst2 = ppstag&0x30; // bits 45
1054 ppst3 = ppstag&0xc0; // bits 67
1055 if ((ppst2 == 0) && (ppst3 == 0) ) {
1056 switch (ppst1) {
1057
1058 case PPS_NULL :
1059 if (lev > 1) cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
1060 break;
1061
1062 case PPS_STRING :
1063 GetRawI4(i4);
1064 if (lev > 1) cout << "<PPS_STRING> tag at position " << hex << cpos << dec
1065 << " Length=" << i4 << endl;
1066 s->seekg(i4,ios::cur);
1067 break;
1068
1069 case PPS_OBJECT :
1070 GetRawU8(cid);
1071 GetRawU8(oid);
1072 cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid
1073 << " ObjectId= " << oid << dec << endl;
1074 break;
1075
1076 case PPS_REFERENCE :
1077 GetRawU8(oid);
1078 GetRawI8(i8);
1079 cout << "<PPS_REFERENCE> tag at position " << hex << cpos << " ObjectId= "
1080 << oid << " OrigPos=" << i8 << dec << endl;
1081 break;
1082
1083 case PPS_TAG_MARK :
1084 cout << "<PPS_TAG_MARK> tag at position " << hex << cpos << dec << endl;
1085 break;
1086
1087 case PPS_ENDOBJECT :
1088 GetRawU8(oid);
1089 cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << " ObjectId= "
1090 << oid << dec << endl;
1091 break;
1092
1093 case PPS_TAG :
1094 GetRawI8(i8);
1095 GetRawI4(i4);
1096 buff = new char[i4+1];
1097 GetRawBytes(buff, i4);
1098 buff[i4] = '\0'; str = buff;
1099 delete[] buff;
1100 cout << "<PPS_TAG> tag at position " << hex << cpos << dec
1101 << " Name= " << str << endl;
1102 break;
1103
1104 case PPS_EOF :
1105 GetRawI8(i8);
1106 cout << "<PPS_EOF> tag at position " << hex << cpos
1107 << " TagPos=" << i8 << dec << endl;
1108 eofok = true;
1109 break;
1110
1111 default :
1112 cerr << " ERROR : Unexpected tag value " << hex << ppstag
1113 << " At position" << cpos << dec << endl;
1114 throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
1115 }
[241]1116 }
[802]1117 else {
1118 string dtype = "???? x";
1119 if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
1120 else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
1121 else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
1122 else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
1123 int_4 dsize = ppst1;
1124 char sb[16];
1125 sprintf(sb, "%d", dsize);
1126 dtype += sb;
1127
1128 switch (ppst2) {
1129
1130 case PPS_SIMPLE :
1131 if (lev > 2) cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec
1132 << " DataType=" << dtype << endl;
1133 s->seekg(dsize, ios::cur);
1134 break;
1135
1136 case PPS_SIMPLE_ARRAY4 :
1137 GetRawI4(i4);
1138 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec
1139 << " DataType=" << dtype << " NElts= " << i4 << endl;
1140 s->seekg((uint_8)dsize*(uint_8)i4, ios::cur);
1141 break;
1142
1143 case PPS_SIMPLE_ARRAY8 :
1144 GetRawU8(ui8);
1145 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec
1146 << " DataType=" << dtype << " NElts= " << ui8 << endl;
1147 s->seekg((uint_8)dsize*ui8, ios::cur);
1148 break;
1149 }
1150 }
[241]1151 }
[802]1152 if (!eofok)
1153 throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
1154
1155 cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl;
1156 cout << " ---------------------------------------------------------- \n" << endl;
1157 return;
[241]1158}
1159
[802]1160void
1161PInPersist::ReadReference(PPersist & ppo)
[241]1162{
[802]1163 PPersist * pr = ReadReference();
1164 ppo.ShareDataReference(*pr);
[241]1165}
1166
[802]1167
1168PPersist *
1169PInPersist::ReadReference()
1170{
1171 uint_8 oid;
1172 int_8 pos;
1173 GetRawU8(oid);
1174 GetRawI8(pos);
1175 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
1176 map<uint_8, PPersist *>::iterator i = objList.find(oid);
1177 if (i != objList.end()) return (*i).second;
1178 else { // We may have skeeped it !
1179 // Let's try to read it
1180 int_8 cpos;
1181#ifdef STREAMPOS_IS_CLASS
1182 cpos = s->tellg().offset();
1183#else
1184 cpos = s->tellg();
1185#endif
1186 s->seekg(pos);
1187 PPersist* ppo = ReadObject();
1188 s->seekg(cpos);
1189 delete ppo;
1190 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
1191
1192 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
1193 if (i2 == objList.end())
1194 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
1195 return (*i2).second;
1196 }
1197}
1198
1199
1200void
1201PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
1202{
1203 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
1204 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
1205 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
1206 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoTag)
1207 // et pas avec une lecture sequentielle ... Reza 03/2000
1208 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
1209 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
1210 PPersist *pp = (*objList.find(oid)).second;
1211 ppo.ShareDataReference(*pp);
1212 }
1213 else {
1214 PPersist * npp = ppo.CloneSharedReference();
1215 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
1216 objList[oid] = npp;
1217 }
1218 return;
1219}
1220
[219]1221//++
1222// Class POutPersist
1223// Lib Outils++
1224// include ppersist.h
1225//
1226// Fichier d'objets persistants, en écriture.
1227//--
1228
1229
1230//++
1231// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
1232//
1233// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
1234// sur machines petit-boutiennes, et gros-boutien sur machines
1235// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
1236// ou PPersist::PPS_BIG_ENDIAN.
1237//--
1238POutPersist::POutPersist(string const& flnm, int endianness)
1239{
1240 if (endianness == -1)
1241 bigEndian = IS_BIG_ENDIAN;
1242 else
1243 bigEndian = endianness;
1244
[802]1245 // PPS (POutPersist stream) Object Id initialisation
1246 pps_OId = 0;
[241]1247 // Output stream creation
1248 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
1249
1250 // Header
[802]1251 PutRawBytes("SOS-SOPHYA-PPersistFile V2 ",32);
[241]1252 PutRawBytes(bigEndian
1253 ? "BIG-ENDIAN "
1254 : "LITTLE-ENDIAN ",32);
1255
1256// ---- GMT creation date of the file
1257 time_t tm = time(NULL);
1258 char datestring[33];
[742]1259 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
[241]1260 for(int i=l; i<32; i++) datestring[i] = ' ';
1261 datestring[32] = '\0';
1262 PutRawBytes(datestring, 32);
[802]1263 filename = flnm;
[219]1264}
1265
1266POutPersist::~POutPersist()
1267{
[241]1268 if (tags.size() == 0) {
[802]1269 PutRawUByte(PPS_EOF);
[241]1270 PutRawI8(-1);
1271 } else {
1272 int_8 tagPos;
1273#ifdef STREAMPOS_IS_CLASS
1274 tagPos = s->tellp().offset();
1275#else
1276 tagPos = s->tellp();
1277#endif
1278 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
1279 string name = (*i).first;
1280 int_8 pos = (*i).second;
[802]1281 PutRawUByte(PPS_TAG); // This is a tag
[241]1282 PutRawI8(pos); // position of previous tag
1283 PutRawI4(name.length()); // length of the name
1284 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
1285 }
[802]1286 PutRawUByte(PPS_EOF);
[241]1287 PutRawI8(tagPos);
1288 }
1289
1290 delete s; // Close the stream
[219]1291}
1292
1293
[241]1294void
1295POutPersist::WriteTag(string const& name)
[219]1296{
[241]1297 if (name.length() > MAXTAGLEN)
1298 throw ParmError("POutPersist::WriteTag tag name too long");
[219]1299
[241]1300 if (tags.find(name) != tags.end())
1301 throw DuplicateIdExc("POutPersist::WriteTag duplicate tag name");
1302
1303 // Get current file position
1304 int_8 tagPos;
1305
[219]1306 #ifdef STREAMPOS_IS_CLASS
[241]1307 tagPos = s->tellp().offset();
[219]1308 #else
[241]1309 tagPos = s->tellp();
[219]1310 #endif
[241]1311
1312 tags[name] = tagPos;
[802]1313 PutRawUByte(PPS_TAG_MARK); // This is a tag
1314 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
[219]1315}
1316
1317//++
1318// void POutPersist::PutByte(char& c)
1319// void POutPersist::PutBytes(void const* ptr, size_t bytes)
1320// void POutPersist::PutR4 (r_4 result)
1321// void POutPersist::PutR4s (r_4 const* tab, size_t n)
1322// void POutPersist::PutR8 (r_8 result)
1323// void POutPersist::PutR8s (r_8 const* tab, size_t n)
1324// void POutPersist::PutI2 (int_2 result)
1325// void POutPersist::PutI2s (int_2 const* tab, size_t n)
1326// void POutPersist::PutU2 (uint_2 result)
1327// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
1328// void POutPersist::PutI4 (int_4 result)
1329// void POutPersist::PutI4s (int_4 const* tab, size_t n)
1330// void POutPersist::PutU4 (uint_4 result)
1331// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
1332// void POutPersist::PutI8 (int_8 result)
1333// void POutPersist::PutI8s (int_8 const* tab, size_t n)
1334// void POutPersist::PutU8 (uint_8 result)
1335// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
[241]1336// void POutPersist::PutStr (string const&)
[219]1337// Ecriture de données portables.. Pour chaque type
1338// de données, on peut écrire une valeur, ou un tableau de valeurs.
1339// void POutPersist::PutLine(char const* ptr, size_t len)
1340// Ecriture d'une ligne de texte dans le fichier PPersist.
1341//--
1342
1343
1344
1345
1346void
[241]1347POutPersist::PutRawBytes(void const* ptr, size_t bytes)
1348{
1349 s->write((char const*)ptr, bytes);
1350}
1351
1352void
1353POutPersist::PutRawByte(char c)
1354{
1355 PutRawBytes(&c, 1);
1356}
1357
1358void
[802]1359POutPersist::PutRawUByte(unsigned char c)
1360{
1361 PutRawBytes(&c, 1);
1362}
1363
1364void
[241]1365POutPersist::PutRawI2 (int_2 val)
1366{
1367 if (bigEndian != IS_BIG_ENDIAN)
1368 bswap2(&val);
1369
1370 PutRawBytes(&val, sizeof(int_2));
1371}
1372
1373void
1374POutPersist::PutRawI4 (int_4 val)
1375{
1376 if (bigEndian != IS_BIG_ENDIAN)
1377 bswap4(&val);
1378
1379 PutRawBytes(&val, sizeof(int_4));
1380}
1381
1382void
1383POutPersist::PutRawI8 (int_8 val)
1384{
1385 if (bigEndian != IS_BIG_ENDIAN)
1386 bswap8(&val);
1387
1388 PutRawBytes(&val, sizeof(int_8));
1389}
1390
1391void
1392POutPersist::PutRawU8 (uint_8 val)
1393{
1394 if (bigEndian != IS_BIG_ENDIAN)
1395 bswap8(&val);
1396
1397 PutRawBytes(&val, sizeof(uint_8));
1398}
1399
1400void
[802]1401POutPersist::PutArrayTag(short datasz, size_t sz, short datatype)
1402// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]1403{
[802]1404 if (sz <= 0x7fffffff) {
1405 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
[241]1406 PutRawI4(sz);
1407 } else {
[802]1408 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
[241]1409 PutRawU8(sz);
1410 }
1411}
1412
1413void
[219]1414POutPersist::PutByte(char c)
1415{
[802]1416 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
[241]1417 PutRawBytes(&c, 1);
[219]1418}
1419
[241]1420
1421
[219]1422void
1423POutPersist::PutBytes(void const* ptr, size_t bytes)
1424{
[802]1425 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]1426 PutRawBytes(ptr, bytes);
[219]1427}
1428
1429void
1430POutPersist::PutR4 (r_4 val)
1431{
[802]1432 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
[241]1433
[219]1434 if (bigEndian != IS_BIG_ENDIAN)
1435 bswap4(&val);
1436
[241]1437 PutRawBytes(&val, sizeof(r_4));
[219]1438}
1439
1440void
1441POutPersist::PutR4s (r_4 const* tab, size_t n)
1442{
[802]1443 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
[241]1444
1445 if (bigEndian == IS_BIG_ENDIAN) {
1446 PutRawBytes(tab, n*sizeof(r_4));
1447 } else {
1448 for (unsigned int i=0; i<n; i++) {
1449 r_4 val = tab[i];
1450 bswap4(&val);
1451 PutRawBytes(&val, sizeof(r_4));
1452 }
1453 }
[219]1454}
1455
1456void
1457POutPersist::PutR8 (r_8 val)
1458{
[802]1459 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
[241]1460
[219]1461 if (bigEndian != IS_BIG_ENDIAN)
1462 bswap8(&val);
1463
[241]1464 PutRawBytes(&val, sizeof(r_8));
[219]1465}
1466
1467void
1468POutPersist::PutR8s (r_8 const* tab, size_t n)
1469{
[802]1470 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
[241]1471
1472 if (bigEndian == IS_BIG_ENDIAN) {
1473 PutRawBytes(tab, n*sizeof(r_8));
1474 } else {
1475 for (unsigned int i=0; i<n; i++) {
1476 r_8 val = tab[i];
1477 bswap8(&val);
1478 PutRawBytes(&val, sizeof(r_8));
1479 }
1480 }
[219]1481}
1482
1483void
1484POutPersist::PutI2 (int_2 val)
1485{
[802]1486 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
[241]1487
[219]1488 if (bigEndian != IS_BIG_ENDIAN)
1489 bswap2(&val);
1490
[241]1491 PutRawBytes(&val, sizeof(int_2));
[219]1492}
1493
1494void
1495POutPersist::PutI2s (int_2 const* tab, size_t n)
1496{
[802]1497 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
[241]1498
1499 if (bigEndian == IS_BIG_ENDIAN) {
1500 PutRawBytes(tab, n*sizeof(int_2));
1501 } else {
1502 for (unsigned int i=0; i<n; i++) {
1503 int_2 val = tab[i];
1504 bswap2(&val);
1505 PutRawBytes(&val, sizeof(int_2));
1506 }
1507 }
[219]1508}
1509
1510void
1511POutPersist::PutU2 (uint_2 val)
1512{
[802]1513 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
[241]1514
[219]1515 if (bigEndian != IS_BIG_ENDIAN)
1516 bswap2(&val);
1517
[241]1518 PutRawBytes(&val, sizeof(uint_2));
[219]1519}
1520
1521void
1522POutPersist::PutU2s (uint_2 const* tab, size_t n)
1523{
[802]1524 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
[241]1525
1526 if (bigEndian == IS_BIG_ENDIAN) {
1527 PutRawBytes(tab, n*sizeof(uint_2));
1528 } else {
1529 for (unsigned int i=0; i<n; i++) {
1530 uint_2 val = tab[i];
1531 bswap2(&val);
1532 PutRawBytes(&val, sizeof(uint_2));
1533 }
1534 }
[219]1535}
1536
1537void
1538POutPersist::PutI4 (int_4 val)
1539{
[802]1540 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
[241]1541
[219]1542 if (bigEndian != IS_BIG_ENDIAN)
1543 bswap4(&val);
1544
[241]1545 PutRawBytes(&val, sizeof(int_4));
[219]1546}
1547
1548void
1549POutPersist::PutI4s (int_4 const* tab, size_t n)
1550{
[802]1551 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
[241]1552
1553 if (bigEndian == IS_BIG_ENDIAN) {
1554 PutRawBytes(tab, n*sizeof(int_4));
1555 } else {
1556 for (unsigned int i=0; i<n; i++) {
1557 int_4 val = tab[i];
1558 bswap4(&val);
1559 PutRawBytes(&val, sizeof(int_4));
1560 }
1561 }
[219]1562}
1563
1564void
1565POutPersist::PutU4 (uint_4 val)
1566{
[802]1567 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
[241]1568
[219]1569 if (bigEndian != IS_BIG_ENDIAN)
1570 bswap4(&val);
1571
[241]1572 PutRawBytes(&val, sizeof(uint_4));
[219]1573}
1574
1575void
1576POutPersist::PutU4s (uint_4 const* tab, size_t n)
1577{
[802]1578 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
[241]1579
1580 if (bigEndian == IS_BIG_ENDIAN) {
1581 PutRawBytes(tab, n*sizeof(uint_4));
1582 } else {
1583 for (unsigned int i=0; i<n; i++) {
1584 uint_4 val = tab[i];
1585 bswap4(&val);
1586 PutRawBytes(&val, sizeof(uint_4));
1587 }
1588 }
[219]1589}
1590
1591void
1592POutPersist::PutI8 (int_8 val)
1593{
[802]1594 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
[241]1595
[219]1596 if (bigEndian != IS_BIG_ENDIAN)
1597 bswap8(&val);
1598
[241]1599 PutRawBytes(&val, sizeof(int_8));
[219]1600}
1601
1602void
1603POutPersist::PutI8s (int_8 const* tab, size_t n)
1604{
[802]1605 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
[241]1606
1607 if (bigEndian == IS_BIG_ENDIAN) {
1608 PutRawBytes(tab, n*sizeof(int_8));
1609 } else {
1610 for (unsigned int i=0; i<n; i++) {
1611 int_8 val = tab[i];
1612 bswap8(&val);
1613 PutRawBytes(&val, sizeof(int_8));
1614 }
1615 }
[219]1616}
1617
1618void
1619POutPersist::PutU8 (uint_8 val)
1620{
[802]1621 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
[241]1622
[219]1623 if (bigEndian != IS_BIG_ENDIAN)
1624 bswap8(&val);
1625
[241]1626 PutRawBytes(&val, sizeof(uint_8));
[219]1627}
1628
1629void
1630POutPersist::PutU8s (uint_8 const* tab, size_t n)
1631{
[802]1632 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
[241]1633
1634 if (bigEndian == IS_BIG_ENDIAN) {
1635 PutRawBytes(tab, n*sizeof(uint_8));
1636 } else {
1637 for (unsigned int i=0; i<n; i++) {
1638 uint_8 val = tab[i];
1639 bswap8(&val);
1640 PutRawBytes(&val, sizeof(uint_8));
1641 }
1642 }
[219]1643}
1644
1645void
[241]1646POutPersist::PutStr(string const& str)
1647{
[802]1648 PutRawUByte(PPS_STRING);
1649 PutRawI4(str.length());
[241]1650 PutRawBytes(str.c_str(), str.length());
1651}
1652
1653void
[219]1654POutPersist::PutLine(char const* ptr, size_t len)
1655{
[802]1656 string str = ptr;
1657 PutStr(str);
1658}
[241]1659
[802]1660
1661void
1662POutPersist::PutObject(AnyDataObj & o)
1663{
1664 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
1665 if (!f)
1666 throw NotFoundExc("PInPersist::PutObject() class not registered");
1667 PPersist* ppo = f();
1668 ppo->SetDataObj(o);
1669 PutPPObject(ppo);
[219]1670}
1671
[241]1672void
[802]1673POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]1674{
[802]1675 WriteTag(tagname);
1676 PutObject(o);
1677}
[219]1678
[802]1679
1680void
1681POutPersist::PutPPObject(PPersist const* obj)
1682{
1683 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
1684
1685 // We have to write the object
1686 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
1687 PutRawUByte(PPS_OBJECT); // We write the Object Tag
1688 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
1689 PutRawU8(oid); // Write the PPS Object Id
[241]1690 obj->WriteSelf(*this);
[802]1691 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1692 PutRawU8(oid); // and again its PPS Object Id
[241]1693}
[219]1694
[241]1695bool
1696POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1697{
[241]1698 if (x == NULL) {
[802]1699 PutRawUByte(PPS_NULL);
[241]1700 return true;
1701 }
[219]1702
[802]1703 int_8 pos;
1704 uint_8 id = findObjectId(x, pos);
1705 if (id > 0) {
1706 PutRawUByte(PPS_REFERENCE);
1707 PutRawU8(id); // Writing the corresponding object Id
1708 PutRawI8(pos); // The original object position
[241]1709 return true;
1710 }
[219]1711
[802]1712 return false; // Object have to be written in stream ...
[219]1713}
1714
[802]1715uint_8
[241]1716POutPersist::assignObjectId(PPersist const* x)
[219]1717{
[802]1718 pps_OId += 16; // We keep the three first bytes for future usage
1719 // Bit 1 non zero -> Object can be referenced
1720 uint_8 id = pps_OId;
1721 uint_8 mid = x->getMemOId();
1722 if (mid > 0) {
1723 int_8 pos;
1724 if (findObjectId(x,pos) > 0)
1725 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
[821]1726 id += 1; // Bit 1 non zero -> Object can be referenced
[802]1727 objreftag rt;
1728 rt.ppsoid = id;
1729#ifdef STREAMPOS_IS_CLASS
1730 rt.ppspos = s->tellp().offset();
1731#else
1732 rt.ppspos = s->tellp();
1733#endif
1734 objList[mid] = rt;
1735 }
[241]1736 return id;
[219]1737}
1738
[802]1739uint_8
1740POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]1741{
[802]1742 pos = -1;
1743 uint_8 mid = x->getMemOId();
1744 if (mid == 0) return(0);
1745 ObjList::iterator i = objList.find(mid);
1746 if (i == objList.end()) return 0;
1747 pos = (*i).second.ppspos;
1748 return (*i).second.ppsoid;
[219]1749}
1750
[241]1751
Note: See TracBrowser for help on using the repository browser.