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

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

Suite modifications PPersist - en particulier, utilisation des RawInOutStream - Reza 22 Nov 2003

File size: 46.4 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{
[2441]338 s.WriteNameTag(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{
[2459]349 if (!s.GotoNameTag(tag))
[241]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{
[2459]403 s = new RawInFileStream(flnm.c_str());
[241]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;
[2441]433 /* #if !(defined(__MWERKS__) || defined(OS_MACOSX)) RZ-DEL */
[742]434 strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
[2441]435 /* #else
[742]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);
[2441]438
[742]439 tm.tm_mon --;
440 tm.tm_year -= 1900;
[2441]441 #endif RZ-DEL */
442
[241]443 creationdate = mktime(&tm);
[802]444 filename = flnm; // keep the filename
445 seqread = true; // To flag non sequential reads
[2459]446 if (scan && s->isSeekable()) Scan();
[219]447}
448
449
450
451PInPersist::~PInPersist()
452{
[802]453 ObjList::iterator i;
454 for(i=objList.begin(); i!= objList.end(); i++)
455 if ((*i).second) delete (*i).second;
[219]456 delete s;
457}
458
459
[802]460string
461PInPersist::CreationDateStr()
462{
463 time_t cdt = CreationDate();
464 string cdate = ctime(&cdt);
465 return(cdate);
466}
467
[219]468void
469PInPersist::Scan()
470{
[241]471 // On cherche la liste des tags, a la fin du fichier
[219]472
[802]473 unsigned char ppstype;
[2459]474 int_8 debut;
[219]475 debut = s->tellg();
476
[1101]477 s->seekg(-(sizeof(int_8)+1), ios::end);
[1063]478
[588]479 GetTypeTag(ppstype);
[241]480 if (ppstype != PPS_EOF)
481 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
[219]482
[241]483 int_8 pos;
484 GetRawI8(pos);
485 if (pos < 0) { // no tags
486 s->seekg(debut);
487 return;
488 }
[219]489
[241]490 char buffer[MAXTAGLEN+1];
491 s->seekg(pos);
492 while (true) {
[588]493 GetTypeTag(ppstype);
[241]494 if (ppstype == PPS_EOF) break;
495
[2441]496 if (ppstype != PPS_NAMETAG_TABLE)
[241]497 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
[219]498
[241]499 GetRawI8(pos);
500 int_4 len;
501 GetRawI4(len);
502 if (len > MAXTAGLEN)
503 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
504 GetRawBytes(buffer, len);
505 buffer[len] = '\0';
[219]506
[241]507 tags[buffer] = pos;
[219]508 }
[241]509 s->seekg(debut);
[219]510}
511
512
[256]513int
[2459]514PInPersist::NbNameTags()
[256]515{
516 return tags.size();
517}
518
[219]519bool
[2441]520PInPersist::GotoPositionTag(int_8 pos)
[219]521{
[2441]522 s->seekg(pos);
523 int_8 tpos;
524 GetRawI8(tpos);
525 if (tpos != pos)
526 throw FileFormatExc("PInPersist::GotoPositionTag() - Wrong tag position!");
527 return true;
528}
529
530bool
531PInPersist::GotoNameTag(string const& name)
532{
[241]533 map<string, int_8>::iterator i = tags.find(name);
534 if (i == tags.end())
535 return false;
[2441]536 // throw NotFoundExc("PInPersist::GotoNameTag tag not found");
[241]537 s->seekg((*i).second);
[802]538 seqread = false;
539 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[219]540 return(true);
541}
542
[2441]543
[256]544bool
[2459]545PInPersist::GotoNameTagNum(int itag)
[256]546{
[582]547 if (itag<0 || itag >= (int)tags.size()) return false;
[256]548 map<string, int_8>::iterator i = tags.begin();
549 for (int j=0; j<itag; j++) i++;
550 s->seekg((*i).second);
[871]551 seqread = false;
[802]552 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[256]553 return(true);
554}
555
[582]556string
557PInPersist::GetTagName(int itag)
558{
559 if (itag<0 || itag >= (int)tags.size()) return "";
560 map<string, int_8>::iterator i = tags.begin();
561 for (int j=0; j<itag; j++) i++;
562 return((*i).first);
563}
[256]564
[802]565string
566PInPersist::GetTagClassName(int itag)
567{
568 // A faire
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// uint_8 cid = (*i).second;
573// return(GetClassName(cid));
574 return("");
575}
576
[582]577static vector<string> * ret_tag_names = NULL;
578vector<string> const &
[2459]579PInPersist::GetNameTags()
[582]580{
581if (ret_tag_names) delete ret_tag_names;
582ret_tag_names = new vector<string> ;
583map<string, int_8>::iterator i;
584for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
585return(*ret_tag_names);
586}
587
[2459]588bool
589PInPersist::SkipToNextObject()
590{
591 // A FAIRE NOV 2003 - REZA
592 return true;
593}
594
[219]595//++
596// void PInPersist::GetByte(char& c)
597// void PInPersist::GetBytes(void* ptr, size_t bytes)
598// void PInPersist::GetR4 (r_4& result)
599// void PInPersist::GetR4s (r_4* tab, size_t n)
600// void PInPersist::GetR8 (r_8& result)
601// void PInPersist::GetR8s (r_8* tab, size_t n)
602// void PInPersist::GetI2 (int_2& result)
603// void PInPersist::GetI2s (int_2* tab, size_t n)
604// void PInPersist::GetU2 (uint_2& result)
605// void PInPersist::GetU2s (uint_2* tab, size_t n)
606// void PInPersist::GetI4 (int_4& result)
607// void PInPersist::GetI4s (int_4* tab, size_t n)
608// void PInPersist::GetU4 (uint_4& result)
609// void PInPersist::GetU4s (uint_4* tab, size_t n)
610// void PInPersist::GetI8 (int_8& result)
611// void PInPersist::GetI8s (int_8* tab, size_t n)
612// void PInPersist::GetU8 (uint_8& result)
613// void PInPersist::GetU8s (uint_8* tab, size_t n)
614// Lecture de données portables depuis le fichier PPersist. Pour chaque type
615// de données, on peut lire une valeur, ou un tableau de valeurs.
616// void PInPersist::GetLine(char* ptr, size_t len)
617// Lecture d'une ligne de texte depuis le fichier PPersist.
618//--
619
620
[588]621void
[802]622PInPersist::GetTypeTag(unsigned char& c)
[588]623{
[2441]624 int_8 tpos;
625 c = PPS_NAMETAG_MARK;
626 while ( (c == PPS_NAMETAG_MARK) || (c == PPS_POSTAG_MARK) ) {
627 GetRawUByte(c);
628 if (c == PPS_POSTAG_MARK) GetRawI8(tpos);
629 }
630 // while (c == PPS_NAMETAG_MARK) { Il ne faut plus faire ca !
[802]631 // objList.clear(); $CHECK$ Reza 03/2000
632 // GetRawByte(c);
633 // }
[588]634}
[241]635
[588]636
[219]637void
[241]638PInPersist::GetRawByte(char& c)
639{
640 GetRawBytes(&c, 1);
641}
642
643void
[802]644PInPersist::GetRawUByte(unsigned char& c)
645{
646 GetRawBytes(&c, 1);
647}
648
649void
[241]650PInPersist::GetRawBytes(void* ptr, size_t bytes)
651{
652 s->read((char*)ptr, bytes);
653}
654
655void
656PInPersist::GetRawI2 (int_2& result)
657{
658 GetRawBytes(&result, sizeof(int_2));
659 if (bigEndian != IS_BIG_ENDIAN)
660 bswap2(&result);
661}
662
663void
664PInPersist::GetRawI4 (int_4& result)
665{
666 GetRawBytes(&result, sizeof(int_4));
667 if (bigEndian != IS_BIG_ENDIAN)
668 bswap4(&result);
669}
670
671void
672PInPersist::GetRawI8 (int_8& result)
673{
674 GetRawBytes(&result, sizeof(int_8));
675 if (bigEndian != IS_BIG_ENDIAN)
676 bswap8(&result);
677}
678
679void
680PInPersist::GetRawU8 (uint_8& result)
681{
682 GetRawBytes(&result, sizeof(uint_8));
683 if (bigEndian != IS_BIG_ENDIAN)
684 bswap8(&result);
685}
686
687void
[802]688PInPersist::CheckTag(short datasz, short datatype)
689// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]690{
[802]691 unsigned char ppstype;
[588]692 GetTypeTag(ppstype);
[802]693 if (ppstype != PPS_SIMPLE + datasz + datatype)
[256]694 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]695}
696
697void
[802]698PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
699// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]700{
[802]701 unsigned char ppstype;
[588]702 GetTypeTag(ppstype);
[241]703 size_t filesz;
[802]704 if (sz <= 0x7fffffff) {
705 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
706 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]707 int_4 ff;
708 GetRawI4(ff); filesz=ff;
709 } else {
[802]710 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
711 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]712 uint_8 ff;
713 GetRawU8(ff); filesz=ff;
714 }
715 if (filesz != sz)
[802]716 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
[241]717}
718
719void
720PInPersist::GetByte(char& c)
721{
[802]722 CheckTag(1,PPS_DATATYPE_CHAR);
[241]723 GetRawBytes(&c, 1);
724}
725
[802]726
[241]727void
728PInPersist::GetBytes(void* ptr, size_t bytes)
729{
[802]730 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]731 GetRawBytes(ptr, bytes);
732}
733void
[219]734PInPersist::GetR4 (r_4& result)
735{
[802]736 CheckTag(4,PPS_DATATYPE_FLOAT);
[241]737 GetRawBytes(&result, sizeof(r_4));
[219]738 if (bigEndian != IS_BIG_ENDIAN)
739 bswap4(&result);
740}
741
742
743void
744PInPersist::GetR4s (r_4* tab, size_t n)
745{
[802]746 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
[241]747 GetRawBytes(tab, n*sizeof(r_4));
[219]748 if (bigEndian == IS_BIG_ENDIAN) return;
749
750 for (unsigned int i=0; i<n; i++)
751 bswap4(tab+i);
752
753 return;
754}
755
756void
757PInPersist::GetR8 (r_8& result)
758{
[802]759 CheckTag(8,PPS_DATATYPE_FLOAT);
[241]760 GetRawBytes(&result, sizeof(r_8));
[219]761 if (bigEndian != IS_BIG_ENDIAN)
762 bswap8(&result);
763}
764
765void
766PInPersist::GetR8s (r_8* tab, size_t n)
767{
[802]768 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
[241]769 GetRawBytes(tab, n*sizeof(r_8));
[219]770 if (bigEndian == IS_BIG_ENDIAN) return;
771
772 for (unsigned int i=0; i<n; i++)
773 bswap8(tab+i);
774
775 return;
776}
777
778void
[2441]779PInPersist::GetI1 (int_1& result)
780{
781 CheckTag(1,PPS_DATATYPE_INTEGER);
782 GetRawBytes(&result, sizeof(int_1));
783}
784
785void
786PInPersist::GetI1s (int_1* tab, size_t n)
787{
788 CheckArrayTag(1,n,PPS_DATATYPE_INTEGER);
789 GetRawBytes(tab, n*sizeof(int_1));
790}
791
792void
793PInPersist::GetU1 (uint_1& result)
794{
795 CheckTag(1,PPS_DATATYPE_UNSIGNED);
796 GetRawBytes(&result, sizeof(uint_1));
797}
798
799void
800PInPersist::GetU1s (uint_1* tab, size_t n)
801{
802 CheckArrayTag(1,n,PPS_DATATYPE_UNSIGNED);
803 GetRawBytes(tab, n*sizeof(uint_1));
804}
805
806void
[219]807PInPersist::GetI2 (int_2& result)
808{
[802]809 CheckTag(2,PPS_DATATYPE_INTEGER);
[241]810 GetRawBytes(&result, sizeof(int_2));
[219]811 if (bigEndian != IS_BIG_ENDIAN)
812 bswap2(&result);
813}
814
815void
816PInPersist::GetI2s (int_2* tab, size_t n)
817{
[802]818 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
[241]819 GetRawBytes(tab, n*sizeof(int_2));
[219]820 if (bigEndian == IS_BIG_ENDIAN) return;
821
822 for (unsigned int i=0; i<n; i++)
823 bswap2(tab+i);
824
825 return;
826}
827
828void
829PInPersist::GetU2 (uint_2& result)
830{
[802]831 CheckTag(2,PPS_DATATYPE_UNSIGNED);
[241]832 GetRawBytes(&result, sizeof(uint_2));
[219]833 if (bigEndian != IS_BIG_ENDIAN)
834 bswap2(&result);
835}
836
837void
838PInPersist::GetU2s (uint_2* tab, size_t n)
839{
[802]840 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
[241]841 GetRawBytes(tab, n*sizeof(uint_2));
[219]842 if (bigEndian == IS_BIG_ENDIAN) return;
843
844 for (unsigned int i=0; i<n; i++)
845 bswap2(tab+i);
846
847 return;
848}
849
850void
851PInPersist::GetI4 (int_4& result)
852{
[802]853 CheckTag(4,PPS_DATATYPE_INTEGER);
[241]854 GetRawBytes(&result, sizeof(int_4));
[219]855 if (bigEndian != IS_BIG_ENDIAN)
856 bswap4(&result);
857}
858
859void
860PInPersist::GetI4s (int_4* tab, size_t n)
861{
[802]862 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
[241]863 GetRawBytes(tab, n*sizeof(int_4));
[219]864 if (bigEndian == IS_BIG_ENDIAN) return;
865
866 for (unsigned int i=0; i<n; i++)
867 bswap4(tab+i);
868
869 return;
870}
871
872void
873PInPersist::GetU4 (uint_4& result)
874{
[802]875 CheckTag(4,PPS_DATATYPE_UNSIGNED);
[241]876 GetRawBytes(&result, sizeof(uint_4));
[219]877 if (bigEndian != IS_BIG_ENDIAN)
878 bswap4(&result);
879}
880
881void
882PInPersist::GetU4s (uint_4* tab, size_t n)
883{
[802]884 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
[241]885 GetRawBytes(tab, n*sizeof(uint_4));
[219]886 if (bigEndian == IS_BIG_ENDIAN) return;
887
888 for (unsigned int i=0; i<n; i++)
889 bswap4(tab+i);
890
891 return;
892}
893
894
895void
896PInPersist::GetI8 (int_8& result)
897{
[802]898 CheckTag(8,PPS_DATATYPE_INTEGER);
[241]899 GetRawBytes(&result, sizeof(int_8));
[219]900 if (bigEndian != IS_BIG_ENDIAN)
901 bswap8(&result);
902}
903
904void
905PInPersist::GetI8s (int_8* tab, size_t n)
906{
[802]907 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
[241]908 GetRawBytes(tab, n*sizeof(int_8));
[219]909 if (bigEndian == IS_BIG_ENDIAN) return;
910
911 for (unsigned int i=0; i<n; i++)
912 bswap8(tab+i);
913
914 return;
915}
916
917void
918PInPersist::GetU8 (uint_8& result)
919{
[802]920 CheckTag(8,PPS_DATATYPE_UNSIGNED);
[241]921 GetRawBytes(&result, sizeof(uint_8));
[219]922 if (bigEndian != IS_BIG_ENDIAN)
923 bswap8(&result);
924}
925
926void
927PInPersist::GetU8s (uint_8* tab, size_t n)
928{
[802]929 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
[241]930 GetRawBytes(tab, n*sizeof(uint_8));
[219]931 if (bigEndian == IS_BIG_ENDIAN) return;
932
933 for (unsigned int i=0; i<n; i++)
934 bswap8(tab+i);
935
936 return;
937}
938
939
940void
941PInPersist::GetLine(char* ptr, size_t len)
942{
[802]943 string str;
944 GetStr(str);
945 strncpy(ptr, str.c_str(), len);
946 ptr[len] = '\0';
[219]947}
948
[241]949void
950PInPersist::GetStr(string& str)
951{
[802]952 unsigned char ppstype;
[588]953 GetTypeTag(ppstype);
[241]954 if (ppstype != PPS_STRING)
[802]955 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
956 int_4 len;
957 GetRawI4(len);
[582]958 char * buff = new char[len+1];
[241]959 GetRawBytes(buff, len);
960 buff[len] = '\0';
961 str = buff;
962 delete[] buff;
963}
[219]964
[2441]965void
966PInPersist::GetZ4 (complex<r_4>& result)
967{
968 CheckTag(4,PPS_DATATYPE_COMPLEX);
969 r_4 reim[2];
970 GetRawBytes(reim, 2*sizeof(r_4));
971 if (bigEndian != IS_BIG_ENDIAN) {
972 bswap4(reim);
973 bswap4(reim+1);
974 }
975 result = complex<r_4>(reim[0], reim[1]);
976}
[802]977
[2441]978void
979PInPersist::GetZ4s (complex<r_4>* tab, size_t n)
980{
981 CheckArrayTag(4,n,PPS_DATATYPE_COMPLEX);
982 GetRawBytes(tab, n*2*sizeof(r_4));
983 if (bigEndian == IS_BIG_ENDIAN) return;
984
985 r_4 * p = (r_4 *)tab;
986 for (unsigned int i=0; i<n; i++) {
987 bswap4(p); p++;
988 bswap4(p); p++;
989 }
990 return;
991}
992
993void
994PInPersist::GetZ8 (complex<r_8>& result)
995{
996 CheckTag(8,PPS_DATATYPE_COMPLEX);
997 r_8 reim[2];
998 GetRawBytes(reim, 2*sizeof(r_8));
999 if (bigEndian != IS_BIG_ENDIAN) {
1000 bswap8(reim);
1001 bswap8(reim+1);
1002 }
1003 result = complex<r_8>(reim[0], reim[1]);
1004}
1005
1006void
1007PInPersist::GetZ8s (complex<r_8>* tab, size_t n)
1008{
1009 CheckArrayTag(8,n,PPS_DATATYPE_COMPLEX);
1010 GetRawBytes(tab, n*2*sizeof(r_8));
1011 if (bigEndian == IS_BIG_ENDIAN) return;
1012
1013 r_8 * p = (r_8 *)tab;
1014 for (unsigned int i=0; i<n; i++) {
1015 bswap8(p); p++;
1016 bswap8(p); p++;
1017 }
1018 return;
1019}
1020
1021
1022void
1023PInPersist::GetPosTagTable(int_8* ptab, size_t sz)
1024{
1025 unsigned char ppstype;
1026 GetTypeTag(ppstype);
1027 if (ppstype != PPS_POSTAG_TABLE)
1028 throw FileFormatExc("PInPersist::GetPosTagTable bad type in ppersist stream");
1029 int_4 tsz;
1030 GetRawI4(tsz);
1031 if (tsz != sz)
1032 throw FileFormatExc("PInPersist::GetPosTagTable Size mismatch ");
1033 for(int kk=0; kk<tsz; kk++)
1034 GetRawI8(ptab[kk]);
1035 return;
1036}
1037
1038void
1039PInPersist::GetPosTagTable(vector<int_8>& ptab)
1040{
1041 unsigned char ppstype;
1042 GetTypeTag(ppstype);
1043 if (ppstype != PPS_POSTAG_TABLE)
1044 throw FileFormatExc("PInPersist::GetPosTagTable bad type in ppersist stream");
1045 ptab.clear();
1046 int_4 tsz;
1047 GetRawI4(tsz);
1048 int_8 tpos;
1049 for(int kk=0; kk<tsz; kk++) {
1050 GetRawI8(tpos);
1051 ptab.push_back(tpos);
1052 }
1053 return;
1054}
1055
[241]1056PPersist*
1057PInPersist::ReadObject()
1058{
[802]1059 return(GetPPObject());
1060}
1061
1062void
1063PInPersist::GetObject(AnyDataObj & o)
1064{
1065 GetPPObject(&o);
1066 return;
1067}
1068
1069void
1070PInPersist::GetObject(AnyDataObj & o, string tagname)
1071{
[2459]1072 GotoNameTag(tagname);
[802]1073 GetPPObject(&o);
1074 return;
1075}
1076
1077PPersist*
1078PInPersist::GetPPObject(AnyDataObj * po)
1079{
[241]1080 // Get tag
[802]1081 unsigned char ppstype;
[588]1082 GetTypeTag(ppstype);
[241]1083 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]1084 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]1085 }
1086
1087 if (ppstype == PPS_NULL) {
1088 return NULL;
1089 } else if (ppstype == PPS_OBJECT) {
1090 // Get class id
1091 uint_8 classId;
1092 GetRawU8(classId);
[802]1093 uint_8 oid,oid2;
1094 GetRawU8(oid);
[241]1095
1096 // Get factory method
1097 ClassCreatorFunc f = FindCreatorFunc(classId);
1098 if (!f) {
1099 throw NotFoundExc("PInPersist::ReadObject class not registered");
1100 }
1101
1102 // Create object
1103 PPersist* object = f();
[802]1104 // If a DataObject was specified , we assign it to the PPersistObject
1105 if (po != NULL) object->SetDataObj(*po);
1106
[241]1107 object->ReadSelf(*this);
[802]1108 unsigned char ppstag;
1109 // Read the ENDOBJECT
1110 GetRawUByte(ppstag);
1111 if (ppstag != PPS_ENDOBJECT)
1112 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
1113 GetRawU8(oid2);
1114 if (oid2 != oid)
1115 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
1116
1117 KeepOId(oid, *object);
[241]1118 return object;
[802]1119 }
1120 else if (ppstype == PPS_REFERENCE)
1121 return ReadReference();
1122
1123 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
1124}
1125
1126
1127void
1128PInPersist::AnalyseTags(int lev)
1129{
1130 unsigned char ppstag=0;
[2441]1131 unsigned char ppst1,ppst2,ppst3,ppst30;
[2459]1132 int_8 cpos,fsize;
[802]1133 uint_8 ui8,cid,oid;
1134 int_4 i4;
1135 int_8 i8;
1136 char * buff;
1137 string str;
1138
1139 cout << "\n ---------------------------------------------------------- " << endl;
1140 cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl;
1141
1142
1143 cpos = s->tellg();
1144 s->seekg(0,ios::end);
1145 fsize = s->tellg();
1146 s->seekg(cpos,ios::beg);
1147
1148 cout << " Version= " << Version() << " FileSize= " << fsize
1149 << " Creation Date= " << CreationDateStr() << endl;
1150
1151 uint_8 totntags = 0;
1152 bool eofok = false;
1153
1154 while ( (ppstag != PPS_EOF) && (cpos < fsize) ) {
[2459]1155 cpos = s->tellg();
[802]1156 GetRawUByte(ppstag);
1157 totntags++;
1158
1159 ppst1 = ppstag&0x0f; // bits 0123
1160 ppst2 = ppstag&0x30; // bits 45
1161 ppst3 = ppstag&0xc0; // bits 67
[2441]1162 ppst30 = ppstag&0xc1; // bits 0 67
[802]1163 if ((ppst2 == 0) && (ppst3 == 0) ) {
1164 switch (ppst1) {
1165
1166 case PPS_NULL :
1167 if (lev > 1) cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
1168 break;
1169
1170 case PPS_STRING :
1171 GetRawI4(i4);
1172 if (lev > 1) cout << "<PPS_STRING> tag at position " << hex << cpos << dec
1173 << " Length=" << i4 << endl;
1174 s->seekg(i4,ios::cur);
1175 break;
1176
1177 case PPS_OBJECT :
1178 GetRawU8(cid);
1179 GetRawU8(oid);
1180 cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid
1181 << " ObjectId= " << oid << dec << endl;
1182 break;
1183
1184 case PPS_REFERENCE :
1185 GetRawU8(oid);
1186 GetRawI8(i8);
1187 cout << "<PPS_REFERENCE> tag at position " << hex << cpos << " ObjectId= "
1188 << oid << " OrigPos=" << i8 << dec << endl;
1189 break;
1190
[2441]1191 case PPS_NAMETAG_MARK :
1192 cout << "<PPS_NAMETAG_MARK> tag at position " << hex << cpos << dec << endl;
[802]1193 break;
[2441]1194
1195 case PPS_POSTAG_MARK :
1196 GetRawI8(i8);
1197 cout << "<PPS_POSTAG_MARK> tag at position " << hex << cpos
1198 << " TPos=" << i8 << dec << endl;
1199 break;
[802]1200
1201 case PPS_ENDOBJECT :
1202 GetRawU8(oid);
1203 cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << " ObjectId= "
1204 << oid << dec << endl;
1205 break;
1206
[2441]1207 case PPS_POSTAG_TABLE :
1208 GetRawI4(i4);
1209 for(int kkt=0; kkt<i4; kkt++) GetRawI8(i8);
1210 cout << "<PPS_POSTAG_TABLE> tag at position " << hex << cpos << dec << endl;
1211 break;
1212
1213 case PPS_NAMETAG_TABLE :
[802]1214 GetRawI8(i8);
1215 GetRawI4(i4);
1216 buff = new char[i4+1];
1217 GetRawBytes(buff, i4);
1218 buff[i4] = '\0'; str = buff;
1219 delete[] buff;
1220 cout << "<PPS_TAG> tag at position " << hex << cpos << dec
1221 << " Name= " << str << endl;
1222 break;
1223
1224 case PPS_EOF :
1225 GetRawI8(i8);
1226 cout << "<PPS_EOF> tag at position " << hex << cpos
1227 << " TagPos=" << i8 << dec << endl;
1228 eofok = true;
1229 break;
1230
1231 default :
1232 cerr << " ERROR : Unexpected tag value " << hex << ppstag
1233 << " At position" << cpos << dec << endl;
1234 throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
1235 }
[241]1236 }
[802]1237 else {
1238 string dtype = "???? x";
[2441]1239 if (ppst30 == PPS_DATATYPE_COMPLEX) dtype = "COMPLEX x";
1240 else if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
[802]1241 else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
1242 else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
1243 else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
1244 int_4 dsize = ppst1;
[2441]1245 int_4 dsizeskip = dsize;
1246 if (ppst30 == PPS_DATATYPE_COMPLEX) {
1247 dsize--;
1248 dsizeskip = 2*dsize;
1249 }
[802]1250 char sb[16];
1251 sprintf(sb, "%d", dsize);
1252 dtype += sb;
1253
1254 switch (ppst2) {
1255
1256 case PPS_SIMPLE :
1257 if (lev > 2) cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec
1258 << " DataType=" << dtype << endl;
[2441]1259 s->seekg(dsizeskip, ios::cur);
[802]1260 break;
1261
1262 case PPS_SIMPLE_ARRAY4 :
1263 GetRawI4(i4);
1264 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec
1265 << " DataType=" << dtype << " NElts= " << i4 << endl;
[2459]1266 s->seekg((int_8)dsizeskip*(int_8)i4, ios::cur);
[802]1267 break;
1268
1269 case PPS_SIMPLE_ARRAY8 :
1270 GetRawU8(ui8);
1271 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec
1272 << " DataType=" << dtype << " NElts= " << ui8 << endl;
[2459]1273 s->seekg((int_8)dsizeskip*ui8, ios::cur);
[802]1274 break;
1275 }
1276 }
[241]1277 }
[802]1278 if (!eofok)
1279 throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
1280
1281 cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl;
1282 cout << " ---------------------------------------------------------- \n" << endl;
1283 return;
[241]1284}
1285
[802]1286void
1287PInPersist::ReadReference(PPersist & ppo)
[241]1288{
[802]1289 PPersist * pr = ReadReference();
1290 ppo.ShareDataReference(*pr);
[241]1291}
1292
[802]1293
1294PPersist *
1295PInPersist::ReadReference()
1296{
1297 uint_8 oid;
1298 int_8 pos;
1299 GetRawU8(oid);
1300 GetRawI8(pos);
1301 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
1302 map<uint_8, PPersist *>::iterator i = objList.find(oid);
1303 if (i != objList.end()) return (*i).second;
1304 else { // We may have skeeped it !
1305 // Let's try to read it
1306 int_8 cpos;
1307 cpos = s->tellg();
1308 s->seekg(pos);
1309 PPersist* ppo = ReadObject();
1310 s->seekg(cpos);
1311 delete ppo;
1312 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
1313
1314 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
1315 if (i2 == objList.end())
1316 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
1317 return (*i2).second;
1318 }
1319}
1320
1321
1322void
1323PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
1324{
1325 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
1326 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
1327 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
[2459]1328 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
[802]1329 // et pas avec une lecture sequentielle ... Reza 03/2000
1330 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
1331 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
1332 PPersist *pp = (*objList.find(oid)).second;
1333 ppo.ShareDataReference(*pp);
1334 }
1335 else {
1336 PPersist * npp = ppo.CloneSharedReference();
1337 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
1338 objList[oid] = npp;
1339 }
1340 return;
1341}
1342
[219]1343//++
1344// Class POutPersist
1345// Lib Outils++
1346// include ppersist.h
1347//
1348// Fichier d'objets persistants, en écriture.
1349//--
1350
1351
1352//++
1353// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
1354//
1355// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
1356// sur machines petit-boutiennes, et gros-boutien sur machines
1357// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
1358// ou PPersist::PPS_BIG_ENDIAN.
1359//--
1360POutPersist::POutPersist(string const& flnm, int endianness)
1361{
1362 if (endianness == -1)
1363 bigEndian = IS_BIG_ENDIAN;
1364 else
1365 bigEndian = endianness;
1366
[802]1367 // PPS (POutPersist stream) Object Id initialisation
1368 pps_OId = 0;
[241]1369 // Output stream creation
[2459]1370 s = new RawOutFileStream(flnm.c_str());
[2441]1371 version = 3;
[241]1372 // Header
[2441]1373 PutRawBytes("SOS-SOPHYA-PPersistFile V3 ",32);
[241]1374 PutRawBytes(bigEndian
1375 ? "BIG-ENDIAN "
1376 : "LITTLE-ENDIAN ",32);
1377
1378// ---- GMT creation date of the file
1379 time_t tm = time(NULL);
1380 char datestring[33];
[742]1381 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
[241]1382 for(int i=l; i<32; i++) datestring[i] = ' ';
1383 datestring[32] = '\0';
1384 PutRawBytes(datestring, 32);
[802]1385 filename = flnm;
[219]1386}
1387
1388POutPersist::~POutPersist()
1389{
[241]1390 if (tags.size() == 0) {
[802]1391 PutRawUByte(PPS_EOF);
[241]1392 PutRawI8(-1);
1393 } else {
1394 int_8 tagPos;
1395 tagPos = s->tellp();
1396 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
1397 string name = (*i).first;
1398 int_8 pos = (*i).second;
[2441]1399 PutRawUByte(PPS_NAMETAG_TABLE); // This is a tag
[241]1400 PutRawI8(pos); // position of previous tag
1401 PutRawI4(name.length()); // length of the name
1402 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
1403 }
[802]1404 PutRawUByte(PPS_EOF);
[241]1405 PutRawI8(tagPos);
1406 }
1407
1408 delete s; // Close the stream
[219]1409}
1410
[2441]1411int_8
1412POutPersist::WritePositionTag()
1413{
1414 int_8 tagpos;
1415 tagpos = s->tellp();
1416 PutRawByte(PPS_POSTAG_MARK);
1417 PutI8(tagpos);
1418 return(tagpos);
1419}
[219]1420
[241]1421void
[2441]1422POutPersist::WriteNameTag(string const& name)
[219]1423{
[241]1424 if (name.length() > MAXTAGLEN)
[2441]1425 throw ParmError("POutPersist::WriteNameTag tag name too long");
[219]1426
[241]1427 if (tags.find(name) != tags.end())
[2441]1428 throw DuplicateIdExc("POutPersist::WriteNameTag duplicate tag name");
[241]1429
1430 // Get current file position
1431 int_8 tagPos;
1432 tagPos = s->tellp();
1433
1434 tags[name] = tagPos;
[2441]1435 PutRawUByte(PPS_NAMETAG_MARK); // This is a tag
[802]1436 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
[219]1437}
1438
1439//++
1440// void POutPersist::PutByte(char& c)
1441// void POutPersist::PutBytes(void const* ptr, size_t bytes)
1442// void POutPersist::PutR4 (r_4 result)
1443// void POutPersist::PutR4s (r_4 const* tab, size_t n)
1444// void POutPersist::PutR8 (r_8 result)
1445// void POutPersist::PutR8s (r_8 const* tab, size_t n)
1446// void POutPersist::PutI2 (int_2 result)
1447// void POutPersist::PutI2s (int_2 const* tab, size_t n)
1448// void POutPersist::PutU2 (uint_2 result)
1449// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
1450// void POutPersist::PutI4 (int_4 result)
1451// void POutPersist::PutI4s (int_4 const* tab, size_t n)
1452// void POutPersist::PutU4 (uint_4 result)
1453// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
1454// void POutPersist::PutI8 (int_8 result)
1455// void POutPersist::PutI8s (int_8 const* tab, size_t n)
1456// void POutPersist::PutU8 (uint_8 result)
1457// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
[241]1458// void POutPersist::PutStr (string const&)
[219]1459// Ecriture de données portables.. Pour chaque type
1460// de données, on peut écrire une valeur, ou un tableau de valeurs.
1461// void POutPersist::PutLine(char const* ptr, size_t len)
1462// Ecriture d'une ligne de texte dans le fichier PPersist.
1463//--
1464
1465
1466
1467
1468void
[241]1469POutPersist::PutRawBytes(void const* ptr, size_t bytes)
1470{
1471 s->write((char const*)ptr, bytes);
1472}
1473
1474void
1475POutPersist::PutRawByte(char c)
1476{
1477 PutRawBytes(&c, 1);
1478}
1479
1480void
[802]1481POutPersist::PutRawUByte(unsigned char c)
1482{
1483 PutRawBytes(&c, 1);
1484}
1485
1486void
[241]1487POutPersist::PutRawI2 (int_2 val)
1488{
1489 if (bigEndian != IS_BIG_ENDIAN)
1490 bswap2(&val);
1491
1492 PutRawBytes(&val, sizeof(int_2));
1493}
1494
1495void
1496POutPersist::PutRawI4 (int_4 val)
1497{
1498 if (bigEndian != IS_BIG_ENDIAN)
1499 bswap4(&val);
1500
1501 PutRawBytes(&val, sizeof(int_4));
1502}
1503
1504void
1505POutPersist::PutRawI8 (int_8 val)
1506{
1507 if (bigEndian != IS_BIG_ENDIAN)
1508 bswap8(&val);
1509
1510 PutRawBytes(&val, sizeof(int_8));
1511}
1512
1513void
1514POutPersist::PutRawU8 (uint_8 val)
1515{
1516 if (bigEndian != IS_BIG_ENDIAN)
1517 bswap8(&val);
1518
1519 PutRawBytes(&val, sizeof(uint_8));
1520}
1521
1522void
[802]1523POutPersist::PutArrayTag(short datasz, size_t sz, short datatype)
1524// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]1525{
[802]1526 if (sz <= 0x7fffffff) {
1527 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
[241]1528 PutRawI4(sz);
1529 } else {
[802]1530 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
[241]1531 PutRawU8(sz);
1532 }
1533}
1534
1535void
[219]1536POutPersist::PutByte(char c)
1537{
[802]1538 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
[241]1539 PutRawBytes(&c, 1);
[219]1540}
1541
[241]1542
1543
[219]1544void
1545POutPersist::PutBytes(void const* ptr, size_t bytes)
1546{
[802]1547 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]1548 PutRawBytes(ptr, bytes);
[219]1549}
1550
1551void
1552POutPersist::PutR4 (r_4 val)
1553{
[802]1554 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
[241]1555
[219]1556 if (bigEndian != IS_BIG_ENDIAN)
1557 bswap4(&val);
1558
[241]1559 PutRawBytes(&val, sizeof(r_4));
[219]1560}
1561
1562void
1563POutPersist::PutR4s (r_4 const* tab, size_t n)
1564{
[802]1565 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
[241]1566
1567 if (bigEndian == IS_BIG_ENDIAN) {
1568 PutRawBytes(tab, n*sizeof(r_4));
1569 } else {
1570 for (unsigned int i=0; i<n; i++) {
1571 r_4 val = tab[i];
1572 bswap4(&val);
1573 PutRawBytes(&val, sizeof(r_4));
1574 }
1575 }
[219]1576}
1577
1578void
1579POutPersist::PutR8 (r_8 val)
1580{
[802]1581 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
[241]1582
[219]1583 if (bigEndian != IS_BIG_ENDIAN)
1584 bswap8(&val);
1585
[241]1586 PutRawBytes(&val, sizeof(r_8));
[219]1587}
1588
1589void
1590POutPersist::PutR8s (r_8 const* tab, size_t n)
1591{
[802]1592 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
[241]1593
1594 if (bigEndian == IS_BIG_ENDIAN) {
1595 PutRawBytes(tab, n*sizeof(r_8));
1596 } else {
1597 for (unsigned int i=0; i<n; i++) {
1598 r_8 val = tab[i];
1599 bswap8(&val);
1600 PutRawBytes(&val, sizeof(r_8));
1601 }
1602 }
[219]1603}
1604
1605void
[2441]1606POutPersist::PutI1 (int_1 val)
1607{
1608 PutRawUByte(PPS_SIMPLE + 1 + PPS_DATATYPE_INTEGER);
1609 PutRawBytes(&val, sizeof(int_1));
1610}
1611
1612void
1613POutPersist::PutI1s (int_1 const* tab, size_t n)
1614{
1615 PutArrayTag(1, n, PPS_DATATYPE_INTEGER);
1616 PutRawBytes(tab, n*sizeof(int_1));
1617}
1618
1619void
1620POutPersist::PutU1 (uint_1 val)
1621{
1622 PutRawUByte(PPS_SIMPLE + 1 + PPS_DATATYPE_UNSIGNED);
1623 PutRawBytes(&val, sizeof(uint_1));
1624}
1625
1626void
1627POutPersist::PutU1s (uint_1 const* tab, size_t n)
1628{
1629 PutArrayTag(1, n, PPS_DATATYPE_UNSIGNED);
1630 PutRawBytes(tab, n*sizeof(uint_1));
1631}
1632
1633void
[219]1634POutPersist::PutI2 (int_2 val)
1635{
[802]1636 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
[241]1637
[219]1638 if (bigEndian != IS_BIG_ENDIAN)
1639 bswap2(&val);
1640
[241]1641 PutRawBytes(&val, sizeof(int_2));
[219]1642}
1643
1644void
1645POutPersist::PutI2s (int_2 const* tab, size_t n)
1646{
[802]1647 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
[241]1648
1649 if (bigEndian == IS_BIG_ENDIAN) {
1650 PutRawBytes(tab, n*sizeof(int_2));
1651 } else {
1652 for (unsigned int i=0; i<n; i++) {
1653 int_2 val = tab[i];
1654 bswap2(&val);
1655 PutRawBytes(&val, sizeof(int_2));
1656 }
1657 }
[219]1658}
1659
1660void
1661POutPersist::PutU2 (uint_2 val)
1662{
[802]1663 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
[241]1664
[219]1665 if (bigEndian != IS_BIG_ENDIAN)
1666 bswap2(&val);
1667
[241]1668 PutRawBytes(&val, sizeof(uint_2));
[219]1669}
1670
1671void
1672POutPersist::PutU2s (uint_2 const* tab, size_t n)
1673{
[802]1674 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
[241]1675
1676 if (bigEndian == IS_BIG_ENDIAN) {
1677 PutRawBytes(tab, n*sizeof(uint_2));
1678 } else {
1679 for (unsigned int i=0; i<n; i++) {
1680 uint_2 val = tab[i];
1681 bswap2(&val);
1682 PutRawBytes(&val, sizeof(uint_2));
1683 }
1684 }
[219]1685}
1686
1687void
1688POutPersist::PutI4 (int_4 val)
1689{
[802]1690 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
[241]1691
[219]1692 if (bigEndian != IS_BIG_ENDIAN)
1693 bswap4(&val);
1694
[241]1695 PutRawBytes(&val, sizeof(int_4));
[219]1696}
1697
1698void
1699POutPersist::PutI4s (int_4 const* tab, size_t n)
1700{
[802]1701 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
[241]1702
1703 if (bigEndian == IS_BIG_ENDIAN) {
1704 PutRawBytes(tab, n*sizeof(int_4));
1705 } else {
1706 for (unsigned int i=0; i<n; i++) {
1707 int_4 val = tab[i];
1708 bswap4(&val);
1709 PutRawBytes(&val, sizeof(int_4));
1710 }
1711 }
[219]1712}
1713
1714void
1715POutPersist::PutU4 (uint_4 val)
1716{
[802]1717 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
[241]1718
[219]1719 if (bigEndian != IS_BIG_ENDIAN)
1720 bswap4(&val);
1721
[241]1722 PutRawBytes(&val, sizeof(uint_4));
[219]1723}
1724
1725void
1726POutPersist::PutU4s (uint_4 const* tab, size_t n)
1727{
[802]1728 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
[241]1729
1730 if (bigEndian == IS_BIG_ENDIAN) {
1731 PutRawBytes(tab, n*sizeof(uint_4));
1732 } else {
1733 for (unsigned int i=0; i<n; i++) {
1734 uint_4 val = tab[i];
1735 bswap4(&val);
1736 PutRawBytes(&val, sizeof(uint_4));
1737 }
1738 }
[219]1739}
1740
1741void
1742POutPersist::PutI8 (int_8 val)
1743{
[802]1744 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
[241]1745
[219]1746 if (bigEndian != IS_BIG_ENDIAN)
1747 bswap8(&val);
1748
[241]1749 PutRawBytes(&val, sizeof(int_8));
[219]1750}
1751
1752void
1753POutPersist::PutI8s (int_8 const* tab, size_t n)
1754{
[802]1755 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
[241]1756
1757 if (bigEndian == IS_BIG_ENDIAN) {
1758 PutRawBytes(tab, n*sizeof(int_8));
1759 } else {
1760 for (unsigned int i=0; i<n; i++) {
1761 int_8 val = tab[i];
1762 bswap8(&val);
1763 PutRawBytes(&val, sizeof(int_8));
1764 }
1765 }
[219]1766}
1767
1768void
1769POutPersist::PutU8 (uint_8 val)
1770{
[802]1771 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
[241]1772
[219]1773 if (bigEndian != IS_BIG_ENDIAN)
1774 bswap8(&val);
1775
[241]1776 PutRawBytes(&val, sizeof(uint_8));
[219]1777}
1778
1779void
1780POutPersist::PutU8s (uint_8 const* tab, size_t n)
1781{
[802]1782 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
[241]1783
1784 if (bigEndian == IS_BIG_ENDIAN) {
1785 PutRawBytes(tab, n*sizeof(uint_8));
1786 } else {
1787 for (unsigned int i=0; i<n; i++) {
1788 uint_8 val = tab[i];
1789 bswap8(&val);
1790 PutRawBytes(&val, sizeof(uint_8));
1791 }
1792 }
[219]1793}
1794
1795void
[241]1796POutPersist::PutStr(string const& str)
1797{
[802]1798 PutRawUByte(PPS_STRING);
1799 PutRawI4(str.length());
[241]1800 PutRawBytes(str.c_str(), str.length());
1801}
1802
1803void
[219]1804POutPersist::PutLine(char const* ptr, size_t len)
1805{
[802]1806 string str = ptr;
1807 PutStr(str);
1808}
[241]1809
[802]1810
1811void
[2441]1812POutPersist::PutZ4 (complex<r_4> val)
1813{
1814 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_COMPLEX);
1815 r_4 reim[2];
1816 reim[0] = val.real();
1817 reim[1] = val.imag();
1818 if (bigEndian != IS_BIG_ENDIAN) {
1819 bswap4(reim);
1820 bswap4(reim+1);
1821 }
1822 PutRawBytes(reim, 2*sizeof(r_4));
1823}
1824
1825void
1826POutPersist::PutZ4s (complex<r_4> const* tab, size_t n)
1827{
1828 PutArrayTag(4, n, PPS_DATATYPE_COMPLEX);
1829
1830 if (bigEndian == IS_BIG_ENDIAN) {
1831 PutRawBytes(tab, n*2*sizeof(r_4));
1832 } else {
1833 for (unsigned int i=0; i<n; i++) {
1834 r_4 reim[2];
1835 reim[0] = tab[i].real();
1836 reim[1] = tab[i].imag();
1837 bswap4(reim);
1838 bswap4(reim+1);
1839 PutRawBytes(reim, 2*sizeof(r_4));
1840 }
1841 }
1842}
1843
1844void
1845POutPersist::PutZ8 (complex<r_8> val)
1846{
1847 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_COMPLEX);
1848 r_8 reim[2];
1849 reim[0] = val.real();
1850 reim[1] = val.imag();
1851 if (bigEndian != IS_BIG_ENDIAN) {
1852 bswap8(reim);
1853 bswap8(reim+1);
1854 }
1855 PutRawBytes(reim, 2*sizeof(r_8));
1856}
1857
1858void
1859POutPersist::PutZ8s (complex<r_8> const* tab, size_t n)
1860{
1861 PutArrayTag(8, n, PPS_DATATYPE_COMPLEX);
1862
1863 if (bigEndian == IS_BIG_ENDIAN) {
1864 PutRawBytes(tab, n*2*sizeof(r_8));
1865 } else {
1866 for (unsigned int i=0; i<n; i++) {
1867 r_8 reim[2];
1868 reim[0] = tab[i].real();
1869 reim[1] = tab[i].imag();
1870 bswap8(reim);
1871 bswap8(reim+1);
1872 PutRawBytes(reim, 2*sizeof(r_8));
1873 }
1874 }
1875}
1876
1877void
1878POutPersist::PutPosTagTable(int_8 const * ptab, size_t sz)
1879{
1880 PutRawUByte(PPS_POSTAG_TABLE);
1881 int_4 tsz = sz;
1882 PutRawI4(tsz);
1883 for(int kk=0; kk<tsz; kk++)
1884 PutRawI8(ptab[kk]);
1885 return;
1886}
1887
1888void
1889POutPersist::PutPosTagTable(vector<int_8> const& ptab)
1890{
1891 PutRawUByte(PPS_POSTAG_TABLE);
1892 int_4 tsz = ptab.size();
1893 PutRawI4(tsz);
1894 for(int kk=0; kk<tsz; kk++)
1895 PutRawI8(ptab[kk]);
1896 return;
1897}
1898
1899void
[802]1900POutPersist::PutObject(AnyDataObj & o)
1901{
1902 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
1903 if (!f)
1904 throw NotFoundExc("PInPersist::PutObject() class not registered");
1905 PPersist* ppo = f();
1906 ppo->SetDataObj(o);
1907 PutPPObject(ppo);
[219]1908}
1909
[241]1910void
[802]1911POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]1912{
[2441]1913 WriteNameTag(tagname);
[802]1914 PutObject(o);
1915}
[219]1916
[802]1917
1918void
1919POutPersist::PutPPObject(PPersist const* obj)
1920{
1921 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
1922
1923 // We have to write the object
1924 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
1925 PutRawUByte(PPS_OBJECT); // We write the Object Tag
1926 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
1927 PutRawU8(oid); // Write the PPS Object Id
[241]1928 obj->WriteSelf(*this);
[802]1929 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1930 PutRawU8(oid); // and again its PPS Object Id
[241]1931}
[219]1932
[241]1933bool
1934POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1935{
[241]1936 if (x == NULL) {
[802]1937 PutRawUByte(PPS_NULL);
[241]1938 return true;
1939 }
[219]1940
[802]1941 int_8 pos;
1942 uint_8 id = findObjectId(x, pos);
1943 if (id > 0) {
1944 PutRawUByte(PPS_REFERENCE);
1945 PutRawU8(id); // Writing the corresponding object Id
1946 PutRawI8(pos); // The original object position
[241]1947 return true;
1948 }
[219]1949
[802]1950 return false; // Object have to be written in stream ...
[219]1951}
1952
[802]1953uint_8
[241]1954POutPersist::assignObjectId(PPersist const* x)
[219]1955{
[802]1956 pps_OId += 16; // We keep the three first bytes for future usage
1957 // Bit 1 non zero -> Object can be referenced
1958 uint_8 id = pps_OId;
1959 uint_8 mid = x->getMemOId();
1960 if (mid > 0) {
1961 int_8 pos;
1962 if (findObjectId(x,pos) > 0)
1963 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
[821]1964 id += 1; // Bit 1 non zero -> Object can be referenced
[802]1965 objreftag rt;
1966 rt.ppsoid = id;
1967 rt.ppspos = s->tellp();
1968 objList[mid] = rt;
1969 }
[241]1970 return id;
[219]1971}
1972
[802]1973uint_8
1974POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]1975{
[802]1976 pos = -1;
1977 uint_8 mid = x->getMemOId();
1978 if (mid == 0) return(0);
1979 ObjList::iterator i = objList.find(mid);
1980 if (i == objList.end()) return 0;
1981 pos = (*i).second.ppspos;
1982 return (*i).second.ppsoid;
[219]1983}
1984
[241]1985
Note: See TracBrowser for help on using the repository browser.