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

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

1) Premiere serie des modifications et ajout fonctionalites pour les PPersist:

  • Ecriture/lecture complex<> et tableaux de complex
  • Ecriture/lecture int_1, uint_1 et tableaux de
  • Tag de positionnement et table de tag de positionnement

2) Adaptation de Read/Write NDataBlock et suppression du fichier piocmplx.h

Reza 03/10/2003

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