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

Last change on this file since 764 was 754, checked in by ansari, 26 years ago

Restruction de Sophya en modules plus petit (TArray , SkyMap, HiStats, ...)

Reza 2/3/2000

File size: 26.2 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"
7#include <fstream.h>
[661]8#include <iostream.h>
[241]9#include <typeinfo>
[219]10
11
12#ifdef __mac__
13#include "unixmac.h"
14#include <SIOUX.h>
15#endif
16
[241]17#define MAXTAGLEN 255
18
[219]19//++
[241]20// Class PIOPersist
[219]21// Lib Outils++
22// include ppersist.h
23//
[241]24// Root class for persistant files. Handles the registration of
25// persistant classes
[219]26//--
27
28//++
[241]29// Links See
[219]30// PPersist
[241]31// PInPersist
32// POutPersist
[219]33//--
34
35
[742]36MD5_CONTEXT PIOPersist::ctx;
[269]37PIOPersist::ClassList * PIOPersist::classList = NULL; // $CHECK$ Reza 26/04/99
[588]38map<string, uint_8> * PIOPersist::typeids = NULL;
[241]39
[269]40//++
41void
42PIOPersist::Initialize()
43// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
44//--
45{
46classList = new PIOPersist::ClassList;
[588]47typeids = new map<string, uint_8>;
[269]48}
[241]49
[219]50//++
51void
[588]52PIOPersist::RegisterClass(uint_8 classId, string typname, ClassCreatorFunc f)
[219]53//
[241]54// Register a new persistant class.
55// The classId is usually a hash of the class name, and this
56// method is called only through the PPersistRegistrar template
57// class, with the PPRegister(className) macro.
[219]58//
59//--
60{
[269]61 if (classList->size() && (classList->find(classId) != classList->end())) {
[219]62 cerr << "RegisterClass : Error, " << hex << classId << dec
63 << " already registered." << endl;
[241]64 throw(DuplicateIdExc("PIOPersist::RegisterClass"));
[219]65 }
66
[269]67 (*classList)[classId] = f;
[588]68 (*typeids)[typname] = classId;
[219]69}
70
71
[241]72PIOPersist::ClassCreatorFunc
73PIOPersist::FindCreatorFunc(uint_8 classId)
[219]74{
[269]75 ClassList::iterator i = classList->find(classId);
76 if (i == classList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
[241]77 return (*i).second;
[219]78}
79
80
81//++
82// Class PPersist
83// Lib Outils++
84// include ppersist.h
85//
86// Classe de base pour des objets persistants. Pour créer un objet
87// persistant :
88// - Hériter de PPersist.
89// - Définir un numéro d'identification de la classe, unique dans Peida
90// - Implémenter "ClassId()"
91// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
92// membres que l'on souhaite écrire, et les relire dans le même ordre.
93// Pour écrire une référence à un objet : l'objet doit être un PPersist,
94// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
95// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
96// fois, il faut que cet objet soit un PShPersist.
97// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
98// les fonctions PutXX/GetXX de PInPersist/POutPersist.
99//
100// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
101// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
102//--
103
104//++
[241]105// Links See
[219]106// PInPersist
107// POutPersist
[241]108// PIOPersist
[219]109//--
110
111//++
112void
113PPersist::Write(string const& fn) const
114//
115// Ecrit l'objet dans un nouveau fichier ppersist "fn".
116//--
117{
118 POutPersist of(fn);
119 Write(of);
120}
121
122//++
123void
124PPersist::Read(string const& fn)
125//
126// Relit l'objet dans le fichier ppersist "fn". Il faut connaître a priori
127// le type de l'objet. Pour une relecture avec création automatique du bon
128// objet, utiliser PPersistMgr::ReadObject.
129//--
130{
131 PInPersist inf(fn);
132 Read(inf);
133}
134
135//++
136void
137PPersist::Write(POutPersist& s) const
138//
139// Ecrit l'objet dans le fichier PPersist.
140//--
141{
[241]142 s.PutObject(this);
[219]143}
144
145
146//++
147void
148PPersist::Read(PInPersist& s)
149//
150// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
151// le type de l'objet. Pour une relecture avec création automatique du bon
[241]152// objet, utiliser PInPersist::ReadObject.
153// Il faut qu'on soit un objet ecrit
[219]154//--
155{
[241]156 // We should be the exact type
157 // Check tag value
158 char ppstype;
[588]159 s.GetTypeTag(ppstype);
[241]160 if (ppstype != PInPersist::PPS_OBJECT) {
[256]161 throw FileFormatExc("PPersist::Read : not an object in flow");
[241]162 }
163
164 // Check class id
165 uint_8 classId;
166 s.GetRawU8(classId);
[588]167 uint_8 myClassId = PIOPersist::getTypeId(typeid(*this).name());
168 if (classId != myClassId) {
[256]169 throw FileFormatExc("PPersist::Read : not the same object type");
[241]170 }
[219]171
[241]172 ReadSelf(s);
[219]173}
174
175//++
[241]176void
177PPersist::Write(POutPersist& s, string const& tag) const
[219]178//
[241]179// Ecrit l'objet dans le fichier PPersist avec un tag
[219]180//--
181{
[241]182 s.WriteTag(tag);
183 s.PutObject(this);
[219]184}
185
186//++
187void
[241]188PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]189//
190// Lit l'objet à la position du tag numéro "tagid".
191//--
192{
[241]193 if (!s.GotoTag(tag))
194 throw NotFoundExc("PPersist::ReadAtTag tag not found");
195 Read(s);
[219]196}
197
198
199//++
200// virtual void PPersist::ReadSelf(PInPersist&)=0
201// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
202// et PPersistMgr::ReadObject. Il faut relire les variables membres,
203// dans l'ordre où elles ont été écrites par WriteSelf.
204// virtual void PPersist::WriteSelf(POutPersist&) const=0
205// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
206// Il faut écrire les variables membres,
207// dans l'ordre où elles seront relues par ReadSelf.
208//--
209
210
211
212//++
213// Class PInPersist
214// Lib Outils++
215// include ppersist.h
216//
217// Fichier d'objets persistants, en lecture.
218//--
219
220//++
221PInPersist::PInPersist(string const& flnm, bool scan)
222//
223// Constructeur. Ouvre le fichier.
224//--
225{
[241]226 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
227
228 // Read and check header
229
[219]230 char rbuf[36];
[241]231 GetRawBytes(rbuf, 32);
[576]232 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
[241]233 throw FileFormatExc("PInPersist::PInPersist bad header");
[219]234 }
[241]235 version = atoi(rbuf+24);
236
237 // read endianness
238 GetRawBytes(rbuf, 32);
239 if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
240 bigEndian = true;
241 else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
242 bigEndian = false;
243 else {
244 throw FileFormatExc("PInPersist::PInPersist bad header - endianness");
245 }
246
247 // read creation date
248 GetRawBytes(rbuf, 32);
249 rbuf[32] = '\0';
250 struct tm tm;
[742]251 #ifndef __MWERKS__
252 strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
253 #else
254 sscanf(rbuf,"%2d/%2d/%4d %2d:%2d:%2d GMT",&tm.tm_mday,&tm.tm_mon,&tm.tm_year,
255 &tm.tm_hour,&tm.tm_min,&tm.tm_sec);
256 tm.tm_mon --;
257 tm.tm_year -= 1900;
258 #endif
[241]259 creationdate = mktime(&tm);
260
261 if (scan) Scan();
[219]262}
263
264
265
266PInPersist::~PInPersist()
267{
268 delete s;
269}
270
271
272void
273PInPersist::Scan()
274{
[241]275 // On cherche la liste des tags, a la fin du fichier
[219]276
[241]277 char ppstype;
278 size_t debut;
279#ifdef STREAMPOS_IS_CLASS
[219]280 debut = s->tellg().offset();
[241]281#else
[219]282 debut = s->tellg();
[241]283#endif
[219]284
[241]285 // Find tag entries at end of file
286 s->seekg(-(sizeof(int_8)+1), ios::end);
[588]287 GetTypeTag(ppstype);
[241]288 if (ppstype != PPS_EOF)
289 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
[219]290
[241]291 int_8 pos;
292 GetRawI8(pos);
293 if (pos < 0) { // no tags
294 s->seekg(debut);
295 return;
296 }
[219]297
[241]298 char buffer[MAXTAGLEN+1];
299 s->seekg(pos);
300 while (true) {
[588]301 GetTypeTag(ppstype);
[241]302 if (ppstype == PPS_EOF) break;
303
304 if (ppstype != PPS_TAG)
305 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
[219]306
[241]307 GetRawI8(pos);
308 int_4 len;
309 GetRawI4(len);
310 if (len > MAXTAGLEN)
311 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
312 GetRawBytes(buffer, len);
313 buffer[len] = '\0';
[219]314
[241]315 tags[buffer] = pos;
[219]316 }
[241]317 s->seekg(debut);
[219]318}
319
320
[256]321int
322PInPersist::NbTags()
323{
324 return tags.size();
325}
326
[219]327bool
[241]328PInPersist::GotoTag(string const& name)
[219]329{
[241]330 map<string, int_8>::iterator i = tags.find(name);
331 if (i == tags.end())
332 return false;
333 // throw NotFoundExc("PInPersist::GotoTag tag not found");
334 s->seekg((*i).second);
[588]335 objList.clear(); // $CHECK$ EA 171199
[219]336 return(true);
337}
338
[256]339bool
340PInPersist::GotoTagNum(int itag)
341{
[582]342 if (itag<0 || itag >= (int)tags.size()) return false;
[256]343 map<string, int_8>::iterator i = tags.begin();
344 for (int j=0; j<itag; j++) i++;
345 s->seekg((*i).second);
[588]346 objList.clear(); // $CHECK$ EA 171199
[256]347 return(true);
348}
349
[582]350string
351PInPersist::GetTagName(int itag)
352{
353 if (itag<0 || itag >= (int)tags.size()) return "";
354 map<string, int_8>::iterator i = tags.begin();
355 for (int j=0; j<itag; j++) i++;
356 return((*i).first);
357}
[256]358
[582]359static vector<string> * ret_tag_names = NULL;
360vector<string> const &
361PInPersist::GetTagNames()
362{
363if (ret_tag_names) delete ret_tag_names;
364ret_tag_names = new vector<string> ;
365map<string, int_8>::iterator i;
366for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
367return(*ret_tag_names);
368}
369
[219]370//++
371// void PInPersist::GetByte(char& c)
372// void PInPersist::GetBytes(void* ptr, size_t bytes)
373// void PInPersist::GetR4 (r_4& result)
374// void PInPersist::GetR4s (r_4* tab, size_t n)
375// void PInPersist::GetR8 (r_8& result)
376// void PInPersist::GetR8s (r_8* tab, size_t n)
377// void PInPersist::GetI2 (int_2& result)
378// void PInPersist::GetI2s (int_2* tab, size_t n)
379// void PInPersist::GetU2 (uint_2& result)
380// void PInPersist::GetU2s (uint_2* tab, size_t n)
381// void PInPersist::GetI4 (int_4& result)
382// void PInPersist::GetI4s (int_4* tab, size_t n)
383// void PInPersist::GetU4 (uint_4& result)
384// void PInPersist::GetU4s (uint_4* tab, size_t n)
385// void PInPersist::GetI8 (int_8& result)
386// void PInPersist::GetI8s (int_8* tab, size_t n)
387// void PInPersist::GetU8 (uint_8& result)
388// void PInPersist::GetU8s (uint_8* tab, size_t n)
389// Lecture de données portables depuis le fichier PPersist. Pour chaque type
390// de données, on peut lire une valeur, ou un tableau de valeurs.
391// void PInPersist::GetLine(char* ptr, size_t len)
392// Lecture d'une ligne de texte depuis le fichier PPersist.
393//--
394
395
396static inline void bswap8(void* p)
397{
398 uint_8 tmp = *(uint_8*)p;
399 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
400 ((tmp >> (5*8)) & 0x0000FF00) |
401 ((tmp >> (3*8)) & 0x00FF0000) |
402 ((tmp >> (1*8)) & 0xFF000000) |
403 ((tmp & 0xFF000000) << (1*8)) |
404 ((tmp & 0x00FF0000) << (3*8)) |
405 ((tmp & 0x0000FF00) << (5*8)) |
406 ((tmp & 0x000000FF) << (7*8));
407}
408
409static inline void bswap4(void* p)
410{
411 uint_4 tmp = *(uint_4*)p;
412 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
413 ((tmp >> 8) & 0x0000FF00) |
414 ((tmp & 0x0000FF00) << 8) |
415 ((tmp & 0x000000FF) << 24);
416}
417
418static inline void bswap2(void* p)
419{
420 uint_2 tmp = *(uint_2*)p;
421 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
422 ((tmp & 0x00FF) << 8);
423}
424
[588]425void
426PInPersist::GetTypeTag(char& c)
427{
428 GetRawByte(c);
429 while (c == PPS_TAG_MARK) {
430 objList.clear();
431 GetRawByte(c);
432 }
433}
[241]434
[588]435
[219]436void
[241]437PInPersist::GetRawByte(char& c)
438{
439 GetRawBytes(&c, 1);
440}
441
442void
443PInPersist::GetRawBytes(void* ptr, size_t bytes)
444{
445 s->read((char*)ptr, bytes);
446}
447
448void
449PInPersist::GetRawI2 (int_2& result)
450{
451 GetRawBytes(&result, sizeof(int_2));
452 if (bigEndian != IS_BIG_ENDIAN)
453 bswap2(&result);
454}
455
456void
457PInPersist::GetRawI4 (int_4& result)
458{
459 GetRawBytes(&result, sizeof(int_4));
460 if (bigEndian != IS_BIG_ENDIAN)
461 bswap4(&result);
462}
463
464void
465PInPersist::GetRawI8 (int_8& result)
466{
467 GetRawBytes(&result, sizeof(int_8));
468 if (bigEndian != IS_BIG_ENDIAN)
469 bswap8(&result);
470}
471
472void
473PInPersist::GetRawU8 (uint_8& result)
474{
475 GetRawBytes(&result, sizeof(uint_8));
476 if (bigEndian != IS_BIG_ENDIAN)
477 bswap8(&result);
478}
479
480void
481PInPersist::CheckTag(short datasz)
482{
483 char ppstype;
[588]484 GetTypeTag(ppstype);
[241]485 if (ppstype != PPS_SIMPLE + datasz)
[256]486 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]487}
488
489void
490PInPersist::CheckArrayTag(short datasz, size_t sz)
491{
492 char ppstype;
[588]493 GetTypeTag(ppstype);
[241]494 size_t filesz;
495 if (sz <= 0x7fff) {
496 if (ppstype != PPS_SIMPLE_ARRAY + datasz)
[256]497 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]498 int_2 ff;
499 GetRawI2(ff); filesz=ff;
500 } else if (sz <= 0x7fffffff) {
501 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
[256]502 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]503 int_4 ff;
504 GetRawI4(ff); filesz=ff;
505 } else {
506 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
[256]507 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]508 uint_8 ff;
509 GetRawU8(ff); filesz=ff;
510 }
511 if (filesz != sz)
[256]512 throw FileFormatExc("PInPersist::CheckTag bad array size in ppersist file");
[241]513}
514
515void
516PInPersist::GetByte(char& c)
517{
518 CheckTag(1);
519 GetRawBytes(&c, 1);
520}
521
522void
523PInPersist::GetBytes(void* ptr, size_t bytes)
524{
525 CheckArrayTag(1, bytes);
526 GetRawBytes(ptr, bytes);
527}
528void
[219]529PInPersist::GetR4 (r_4& result)
530{
[241]531 CheckTag(4);
532 GetRawBytes(&result, sizeof(r_4));
[219]533 if (bigEndian != IS_BIG_ENDIAN)
534 bswap4(&result);
535}
536
537
538void
539PInPersist::GetR4s (r_4* tab, size_t n)
540{
[241]541 CheckArrayTag(4,n);
542 GetRawBytes(tab, n*sizeof(r_4));
[219]543 if (bigEndian == IS_BIG_ENDIAN) return;
544
545 for (unsigned int i=0; i<n; i++)
546 bswap4(tab+i);
547
548 return;
549}
550
551void
552PInPersist::GetR8 (r_8& result)
553{
[241]554 CheckTag(8);
555 GetRawBytes(&result, sizeof(r_8));
[219]556 if (bigEndian != IS_BIG_ENDIAN)
557 bswap8(&result);
558}
559
560void
561PInPersist::GetR8s (r_8* tab, size_t n)
562{
[241]563 CheckArrayTag(8,n);
564 GetRawBytes(tab, n*sizeof(r_8));
[219]565 if (bigEndian == IS_BIG_ENDIAN) return;
566
567 for (unsigned int i=0; i<n; i++)
568 bswap8(tab+i);
569
570 return;
571}
572
573void
574PInPersist::GetI2 (int_2& result)
575{
[241]576 CheckTag(2);
577 GetRawBytes(&result, sizeof(int_2));
[219]578 if (bigEndian != IS_BIG_ENDIAN)
579 bswap2(&result);
580}
581
582void
583PInPersist::GetI2s (int_2* tab, size_t n)
584{
[241]585 CheckArrayTag(2,n);
586 GetRawBytes(tab, n*sizeof(int_2));
[219]587 if (bigEndian == IS_BIG_ENDIAN) return;
588
589 for (unsigned int i=0; i<n; i++)
590 bswap2(tab+i);
591
592 return;
593}
594
595void
596PInPersist::GetU2 (uint_2& result)
597{
[241]598 CheckTag(2);
599 GetRawBytes(&result, sizeof(uint_2));
[219]600 if (bigEndian != IS_BIG_ENDIAN)
601 bswap2(&result);
602}
603
604void
605PInPersist::GetU2s (uint_2* tab, size_t n)
606{
[241]607 CheckArrayTag(2,n);
608 GetRawBytes(tab, n*sizeof(uint_2));
[219]609 if (bigEndian == IS_BIG_ENDIAN) return;
610
611 for (unsigned int i=0; i<n; i++)
612 bswap2(tab+i);
613
614 return;
615}
616
617void
618PInPersist::GetI4 (int_4& result)
619{
[241]620 CheckTag(4);
621 GetRawBytes(&result, sizeof(int_4));
[219]622 if (bigEndian != IS_BIG_ENDIAN)
623 bswap4(&result);
624}
625
626void
627PInPersist::GetI4s (int_4* tab, size_t n)
628{
[241]629 CheckArrayTag(4,n);
630 GetRawBytes(tab, n*sizeof(int_4));
[219]631 if (bigEndian == IS_BIG_ENDIAN) return;
632
633 for (unsigned int i=0; i<n; i++)
634 bswap4(tab+i);
635
636 return;
637}
638
639void
640PInPersist::GetU4 (uint_4& result)
641{
[241]642 CheckTag(4);
643 GetRawBytes(&result, sizeof(uint_4));
[219]644 if (bigEndian != IS_BIG_ENDIAN)
645 bswap4(&result);
646}
647
648void
649PInPersist::GetU4s (uint_4* tab, size_t n)
650{
[241]651 CheckArrayTag(4,n);
652 GetRawBytes(tab, n*sizeof(uint_4));
[219]653 if (bigEndian == IS_BIG_ENDIAN) return;
654
655 for (unsigned int i=0; i<n; i++)
656 bswap4(tab+i);
657
658 return;
659}
660
661
662void
663PInPersist::GetI8 (int_8& result)
664{
[241]665 CheckTag(8);
666 GetRawBytes(&result, sizeof(int_8));
[219]667 if (bigEndian != IS_BIG_ENDIAN)
668 bswap8(&result);
669}
670
671void
672PInPersist::GetI8s (int_8* tab, size_t n)
673{
[241]674 CheckArrayTag(8,n);
675 GetRawBytes(tab, n*sizeof(int_8));
[219]676 if (bigEndian == IS_BIG_ENDIAN) return;
677
678 for (unsigned int i=0; i<n; i++)
679 bswap8(tab+i);
680
681 return;
682}
683
684void
685PInPersist::GetU8 (uint_8& result)
686{
[241]687 CheckTag(8);
688 GetRawBytes(&result, sizeof(uint_8));
[219]689 if (bigEndian != IS_BIG_ENDIAN)
690 bswap8(&result);
691}
692
693void
694PInPersist::GetU8s (uint_8* tab, size_t n)
695{
[241]696 CheckArrayTag(8,n);
697 GetRawBytes(tab, n*sizeof(uint_8));
[219]698 if (bigEndian == IS_BIG_ENDIAN) return;
699
700 for (unsigned int i=0; i<n; i++)
701 bswap8(tab+i);
702
703 return;
704}
705
706
707void
708PInPersist::GetLine(char* ptr, size_t len)
709{
[241]710 char ppstype;
[588]711 GetTypeTag(ppstype);
[241]712 if (ppstype != PPS_LINE)
[256]713 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
[241]714 s->getline(ptr, len, '\n');
[219]715}
716
[241]717void
718PInPersist::GetStr(string& str)
719{
720 char ppstype;
[588]721 GetTypeTag(ppstype);
[241]722 if (ppstype != PPS_STRING)
[256]723 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
[241]724 int_2 len;
725 GetRawI2(len);
[582]726 char * buff = new char[len+1];
[241]727 GetRawBytes(buff, len);
728 buff[len] = '\0';
729 str = buff;
730 delete[] buff;
731}
[219]732
[241]733PPersist*
734PInPersist::ReadObject()
735{
736 // Get tag
737 char ppstype;
[588]738 GetTypeTag(ppstype);
[241]739 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]740 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]741 }
742
743 if (ppstype == PPS_NULL) {
744 return NULL;
745 } else if (ppstype == PPS_OBJECT) {
746 // Get class id
747 uint_8 classId;
748 GetRawU8(classId);
749
750 // Get factory method
751 ClassCreatorFunc f = FindCreatorFunc(classId);
752 if (!f) {
753 throw NotFoundExc("PInPersist::ReadObject class not registered");
754 }
755
756 // Create object
757 PPersist* object = f();
758 object->ReadSelf(*this);
759 assignObjectId(object);
760 return object;
761 } else {
762 // Get object id
763 int_4 id;
764 GetRawI4(id);
765 if (id <0 || id>=objList.size()) {
[588]766 char msg[200];
767 sprintf(msg, "PInPersist::ReadObject invalid object id for reference: %d/%d",id,objList.size());
768 throw FileFormatExc(msg);
[241]769 }
770 return objList[id];
771 }
772}
773
774int_4
775PInPersist::assignObjectId(PPersist* x)
776{
777 objList.push_back(x);
778 return objList.size()-1;
779}
780
[219]781//++
782// Class POutPersist
783// Lib Outils++
784// include ppersist.h
785//
786// Fichier d'objets persistants, en écriture.
787//--
788
789
790//++
791// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
792//
793// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
794// sur machines petit-boutiennes, et gros-boutien sur machines
795// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
796// ou PPersist::PPS_BIG_ENDIAN.
797//--
798POutPersist::POutPersist(string const& flnm, int endianness)
799{
800 if (endianness == -1)
801 bigEndian = IS_BIG_ENDIAN;
802 else
803 bigEndian = endianness;
804
[241]805 // Output stream creation
806 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
807
808 // Header
[576]809 PutRawBytes("SOS-SOPHYA-PPersistFile V1 ",32);
[241]810 PutRawBytes(bigEndian
811 ? "BIG-ENDIAN "
812 : "LITTLE-ENDIAN ",32);
813
814// ---- GMT creation date of the file
815 time_t tm = time(NULL);
816 char datestring[33];
[742]817 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
[241]818 for(int i=l; i<32; i++) datestring[i] = ' ';
819 datestring[32] = '\0';
820 PutRawBytes(datestring, 32);
[219]821}
822
823POutPersist::~POutPersist()
824{
[241]825 if (tags.size() == 0) {
826 PutRawByte(PPS_EOF);
827 PutRawI8(-1);
828 } else {
829 int_8 tagPos;
830#ifdef STREAMPOS_IS_CLASS
831 tagPos = s->tellp().offset();
832#else
833 tagPos = s->tellp();
834#endif
835 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
836 string name = (*i).first;
837 int_8 pos = (*i).second;
838 PutRawByte(PPS_TAG); // This is a tag
839 PutRawI8(pos); // position of previous tag
840 PutRawI4(name.length()); // length of the name
841 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
842 }
843 PutRawByte(PPS_EOF);
844 PutRawI8(tagPos);
845 }
846
847 delete s; // Close the stream
[219]848}
849
850
[241]851void
852POutPersist::WriteTag(string const& name)
[219]853{
[241]854 if (name.length() > MAXTAGLEN)
855 throw ParmError("POutPersist::WriteTag tag name too long");
[219]856
[241]857 if (tags.find(name) != tags.end())
858 throw DuplicateIdExc("POutPersist::WriteTag duplicate tag name");
859
860 // Get current file position
861 int_8 tagPos;
862
[219]863 #ifdef STREAMPOS_IS_CLASS
[241]864 tagPos = s->tellp().offset();
[219]865 #else
[241]866 tagPos = s->tellp();
[219]867 #endif
[241]868
869 tags[name] = tagPos;
[588]870 PutRawByte(PPS_TAG_MARK); // This is a tag
871 objList.clear(); // $CHECK$ EA 171199
[219]872}
873
874//++
875// void POutPersist::PutByte(char& c)
876// void POutPersist::PutBytes(void const* ptr, size_t bytes)
877// void POutPersist::PutR4 (r_4 result)
878// void POutPersist::PutR4s (r_4 const* tab, size_t n)
879// void POutPersist::PutR8 (r_8 result)
880// void POutPersist::PutR8s (r_8 const* tab, size_t n)
881// void POutPersist::PutI2 (int_2 result)
882// void POutPersist::PutI2s (int_2 const* tab, size_t n)
883// void POutPersist::PutU2 (uint_2 result)
884// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
885// void POutPersist::PutI4 (int_4 result)
886// void POutPersist::PutI4s (int_4 const* tab, size_t n)
887// void POutPersist::PutU4 (uint_4 result)
888// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
889// void POutPersist::PutI8 (int_8 result)
890// void POutPersist::PutI8s (int_8 const* tab, size_t n)
891// void POutPersist::PutU8 (uint_8 result)
892// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
[241]893// void POutPersist::PutStr (string const&)
[219]894// Ecriture de données portables.. Pour chaque type
895// de données, on peut écrire une valeur, ou un tableau de valeurs.
896// void POutPersist::PutLine(char const* ptr, size_t len)
897// Ecriture d'une ligne de texte dans le fichier PPersist.
898//--
899
900
901
902
903void
[241]904POutPersist::PutRawBytes(void const* ptr, size_t bytes)
905{
906 s->write((char const*)ptr, bytes);
907}
908
909void
910POutPersist::PutRawByte(char c)
911{
912 PutRawBytes(&c, 1);
913}
914
915void
916POutPersist::PutRawI2 (int_2 val)
917{
918 if (bigEndian != IS_BIG_ENDIAN)
919 bswap2(&val);
920
921 PutRawBytes(&val, sizeof(int_2));
922}
923
924void
925POutPersist::PutRawI4 (int_4 val)
926{
927 if (bigEndian != IS_BIG_ENDIAN)
928 bswap4(&val);
929
930 PutRawBytes(&val, sizeof(int_4));
931}
932
933void
934POutPersist::PutRawI8 (int_8 val)
935{
936 if (bigEndian != IS_BIG_ENDIAN)
937 bswap8(&val);
938
939 PutRawBytes(&val, sizeof(int_8));
940}
941
942void
943POutPersist::PutRawU8 (uint_8 val)
944{
945 if (bigEndian != IS_BIG_ENDIAN)
946 bswap8(&val);
947
948 PutRawBytes(&val, sizeof(uint_8));
949}
950
951void
952POutPersist::PutArrayTag(short datasz, size_t sz)
953{
954 if (sz <= 0x7fff) {
955 PutRawByte(PPS_SIMPLE_ARRAY + datasz);
956 PutRawI2(sz);
957 } else if (sz <= 0x7fffffff) {
958 PutRawByte(PPS_SIMPLE_ARRAY4 + datasz);
959 PutRawI4(sz);
960 } else {
961 PutRawByte(PPS_SIMPLE_ARRAY8 + datasz);
962 PutRawU8(sz);
963 }
964}
965
966void
[219]967POutPersist::PutByte(char c)
968{
[241]969 PutRawByte(PPS_SIMPLE + 1);
970 PutRawBytes(&c, 1);
[219]971}
972
[241]973
974
[219]975void
976POutPersist::PutBytes(void const* ptr, size_t bytes)
977{
[241]978 PutArrayTag(1, bytes);
979 PutRawBytes(ptr, bytes);
[219]980}
981
982void
983POutPersist::PutR4 (r_4 val)
984{
[241]985 PutRawByte(PPS_SIMPLE + 4);
986
[219]987 if (bigEndian != IS_BIG_ENDIAN)
988 bswap4(&val);
989
[241]990 PutRawBytes(&val, sizeof(r_4));
[219]991}
992
993void
994POutPersist::PutR4s (r_4 const* tab, size_t n)
995{
[241]996 PutArrayTag(4, n);
997
998 if (bigEndian == IS_BIG_ENDIAN) {
999 PutRawBytes(tab, n*sizeof(r_4));
1000 } else {
1001 for (unsigned int i=0; i<n; i++) {
1002 r_4 val = tab[i];
1003 bswap4(&val);
1004 PutRawBytes(&val, sizeof(r_4));
1005 }
1006 }
[219]1007}
1008
1009void
1010POutPersist::PutR8 (r_8 val)
1011{
[241]1012 PutRawByte(PPS_SIMPLE + 8);
1013
[219]1014 if (bigEndian != IS_BIG_ENDIAN)
1015 bswap8(&val);
1016
[241]1017 PutRawBytes(&val, sizeof(r_8));
[219]1018}
1019
1020void
1021POutPersist::PutR8s (r_8 const* tab, size_t n)
1022{
[241]1023 PutArrayTag(8, n);
1024
1025 if (bigEndian == IS_BIG_ENDIAN) {
1026 PutRawBytes(tab, n*sizeof(r_8));
1027 } else {
1028 for (unsigned int i=0; i<n; i++) {
1029 r_8 val = tab[i];
1030 bswap8(&val);
1031 PutRawBytes(&val, sizeof(r_8));
1032 }
1033 }
[219]1034}
1035
1036void
1037POutPersist::PutI2 (int_2 val)
1038{
[241]1039 PutRawByte(PPS_SIMPLE + 2);
1040
[219]1041 if (bigEndian != IS_BIG_ENDIAN)
1042 bswap2(&val);
1043
[241]1044 PutRawBytes(&val, sizeof(int_2));
[219]1045}
1046
1047void
1048POutPersist::PutI2s (int_2 const* tab, size_t n)
1049{
[241]1050 PutArrayTag(2, n);
1051
1052 if (bigEndian == IS_BIG_ENDIAN) {
1053 PutRawBytes(tab, n*sizeof(int_2));
1054 } else {
1055 for (unsigned int i=0; i<n; i++) {
1056 int_2 val = tab[i];
1057 bswap2(&val);
1058 PutRawBytes(&val, sizeof(int_2));
1059 }
1060 }
[219]1061}
1062
1063void
1064POutPersist::PutU2 (uint_2 val)
1065{
[241]1066 PutRawByte(PPS_SIMPLE + 2);
1067
[219]1068 if (bigEndian != IS_BIG_ENDIAN)
1069 bswap2(&val);
1070
[241]1071 PutRawBytes(&val, sizeof(uint_2));
[219]1072}
1073
1074void
1075POutPersist::PutU2s (uint_2 const* tab, size_t n)
1076{
[241]1077 PutArrayTag(2, n);
1078
1079 if (bigEndian == IS_BIG_ENDIAN) {
1080 PutRawBytes(tab, n*sizeof(uint_2));
1081 } else {
1082 for (unsigned int i=0; i<n; i++) {
1083 uint_2 val = tab[i];
1084 bswap2(&val);
1085 PutRawBytes(&val, sizeof(uint_2));
1086 }
1087 }
[219]1088}
1089
1090void
1091POutPersist::PutI4 (int_4 val)
1092{
[241]1093 PutRawByte(PPS_SIMPLE + 4);
1094
[219]1095 if (bigEndian != IS_BIG_ENDIAN)
1096 bswap4(&val);
1097
[241]1098 PutRawBytes(&val, sizeof(int_4));
[219]1099}
1100
1101void
1102POutPersist::PutI4s (int_4 const* tab, size_t n)
1103{
[241]1104 PutArrayTag(4, n);
1105
1106 if (bigEndian == IS_BIG_ENDIAN) {
1107 PutRawBytes(tab, n*sizeof(int_4));
1108 } else {
1109 for (unsigned int i=0; i<n; i++) {
1110 int_4 val = tab[i];
1111 bswap4(&val);
1112 PutRawBytes(&val, sizeof(int_4));
1113 }
1114 }
[219]1115}
1116
1117void
1118POutPersist::PutU4 (uint_4 val)
1119{
[241]1120 PutRawByte(PPS_SIMPLE + 4);
1121
[219]1122 if (bigEndian != IS_BIG_ENDIAN)
1123 bswap4(&val);
1124
[241]1125 PutRawBytes(&val, sizeof(uint_4));
[219]1126}
1127
1128void
1129POutPersist::PutU4s (uint_4 const* tab, size_t n)
1130{
[241]1131 PutArrayTag(4, n);
1132
1133 if (bigEndian == IS_BIG_ENDIAN) {
1134 PutRawBytes(tab, n*sizeof(uint_4));
1135 } else {
1136 for (unsigned int i=0; i<n; i++) {
1137 uint_4 val = tab[i];
1138 bswap4(&val);
1139 PutRawBytes(&val, sizeof(uint_4));
1140 }
1141 }
[219]1142}
1143
1144void
1145POutPersist::PutI8 (int_8 val)
1146{
[241]1147 PutRawByte(PPS_SIMPLE + 8);
1148
[219]1149 if (bigEndian != IS_BIG_ENDIAN)
1150 bswap8(&val);
1151
[241]1152 PutRawBytes(&val, sizeof(int_8));
[219]1153}
1154
1155void
1156POutPersist::PutI8s (int_8 const* tab, size_t n)
1157{
[241]1158 PutArrayTag(8, n);
1159
1160 if (bigEndian == IS_BIG_ENDIAN) {
1161 PutRawBytes(tab, n*sizeof(int_8));
1162 } else {
1163 for (unsigned int i=0; i<n; i++) {
1164 int_8 val = tab[i];
1165 bswap8(&val);
1166 PutRawBytes(&val, sizeof(int_8));
1167 }
1168 }
[219]1169}
1170
1171void
1172POutPersist::PutU8 (uint_8 val)
1173{
[241]1174 PutRawByte(PPS_SIMPLE + 8);
1175
[219]1176 if (bigEndian != IS_BIG_ENDIAN)
1177 bswap8(&val);
1178
[241]1179 PutRawBytes(&val, sizeof(uint_8));
[219]1180}
1181
1182void
1183POutPersist::PutU8s (uint_8 const* tab, size_t n)
1184{
[241]1185 PutArrayTag(8, n);
1186
1187 if (bigEndian == IS_BIG_ENDIAN) {
1188 PutRawBytes(tab, n*sizeof(uint_8));
1189 } else {
1190 for (unsigned int i=0; i<n; i++) {
1191 uint_8 val = tab[i];
1192 bswap8(&val);
1193 PutRawBytes(&val, sizeof(uint_8));
1194 }
1195 }
[219]1196}
1197
1198void
[241]1199POutPersist::PutStr(string const& str)
1200{
1201 PutRawByte(PPS_STRING);
1202 PutRawI2(str.length());
1203 PutRawBytes(str.c_str(), str.length());
1204}
1205
1206void
[219]1207POutPersist::PutLine(char const* ptr, size_t len)
1208{
[241]1209 PutRawByte(PPS_LINE);
1210
[219]1211 if (len == 0) len = strlen(ptr);
[241]1212 PutRawBytes(ptr, len);
1213 PutRawByte('\n');
[219]1214}
1215
[241]1216void
1217POutPersist::PutObject(PPersist const* obj)
1218{
1219 if (serializeNullAndRepeat(obj)) return;
[219]1220
[241]1221 PutRawByte(PPS_OBJECT);
[588]1222 PutRawU8(getTypeId(typeid(*obj).name()));
1223 //PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
[241]1224 assignObjectId(obj);
1225 obj->WriteSelf(*this);
1226}
[219]1227
[241]1228bool
1229POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1230{
[241]1231 if (x == NULL) {
1232 PutRawByte(PPS_NULL);
1233 return true;
1234 }
[219]1235
[241]1236 int_4 id = findObjectId(x);
1237 if (id >= 0) {
1238 PutRawByte(PPS_REFERENCE);
1239 PutRawI4(id);
1240 return true;
1241 }
[219]1242
[241]1243 return false;
[219]1244}
1245
[241]1246int_4
1247POutPersist::assignObjectId(PPersist const* x)
[219]1248{
[241]1249 int_4 id = objList.size();
1250 objList[x] = id;
1251 return id;
[219]1252}
1253
[241]1254int_4
1255POutPersist::findObjectId(PPersist const* x)
[219]1256{
[241]1257 ObjList::iterator i = objList.find(x);
1258 if (i == objList.end()) return -1;
1259 return (*i).second;
[219]1260}
1261
[241]1262
Note: See TracBrowser for help on using the repository browser.