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
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 <fstream.h>
8#include <iostream.h>
9#include <typeinfo>
10
11
12#ifdef __mac__
13#include "unixmac.h"
14#include <SIOUX.h>
15#endif
16
17#define MAXTAGLEN 255
18
19//++
20// Class PIOPersist
21// Lib Outils++
22// include ppersist.h
23//
24// Root class for persistant files. Handles the registration of
25// persistant classes
26//--
27
28//++
29// Links See
30// PPersist
31// PInPersist
32// POutPersist
33//--
34
35
36MD5_CONTEXT PIOPersist::ctx;
37PIOPersist::ClassList * PIOPersist::classList = NULL; // $CHECK$ Reza 26/04/99
38map<string, uint_8> * PIOPersist::typeids = NULL;
39
40//++
41void
42PIOPersist::Initialize()
43// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
44//--
45{
46classList = new PIOPersist::ClassList;
47typeids = new map<string, uint_8>;
48}
49
50//++
51void
52PIOPersist::RegisterClass(uint_8 classId, string typname, ClassCreatorFunc f)
53//
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.
58//
59//--
60{
61 if (classList->size() && (classList->find(classId) != classList->end())) {
62 cerr << "RegisterClass : Error, " << hex << classId << dec
63 << " already registered." << endl;
64 throw(DuplicateIdExc("PIOPersist::RegisterClass"));
65 }
66
67 (*classList)[classId] = f;
68 (*typeids)[typname] = classId;
69}
70
71
72PIOPersist::ClassCreatorFunc
73PIOPersist::FindCreatorFunc(uint_8 classId)
74{
75 ClassList::iterator i = classList->find(classId);
76 if (i == classList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
77 return (*i).second;
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//++
105// Links See
106// PInPersist
107// POutPersist
108// PIOPersist
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{
142 s.PutObject(this);
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
152// objet, utiliser PInPersist::ReadObject.
153// Il faut qu'on soit un objet ecrit
154//--
155{
156 // We should be the exact type
157 // Check tag value
158 char ppstype;
159 s.GetTypeTag(ppstype);
160 if (ppstype != PInPersist::PPS_OBJECT) {
161 throw FileFormatExc("PPersist::Read : not an object in flow");
162 }
163
164 // Check class id
165 uint_8 classId;
166 s.GetRawU8(classId);
167 uint_8 myClassId = PIOPersist::getTypeId(typeid(*this).name());
168 if (classId != myClassId) {
169 throw FileFormatExc("PPersist::Read : not the same object type");
170 }
171
172 ReadSelf(s);
173}
174
175//++
176void
177PPersist::Write(POutPersist& s, string const& tag) const
178//
179// Ecrit l'objet dans le fichier PPersist avec un tag
180//--
181{
182 s.WriteTag(tag);
183 s.PutObject(this);
184}
185
186//++
187void
188PPersist::ReadAtTag(PInPersist& s, string const& tag)
189//
190// Lit l'objet à la position du tag numéro "tagid".
191//--
192{
193 if (!s.GotoTag(tag))
194 throw NotFoundExc("PPersist::ReadAtTag tag not found");
195 Read(s);
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{
226 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
227
228 // Read and check header
229
230 char rbuf[36];
231 GetRawBytes(rbuf, 32);
232 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
233 throw FileFormatExc("PInPersist::PInPersist bad header");
234 }
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;
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
259 creationdate = mktime(&tm);
260
261 if (scan) Scan();
262}
263
264
265
266PInPersist::~PInPersist()
267{
268 delete s;
269}
270
271
272void
273PInPersist::Scan()
274{
275 // On cherche la liste des tags, a la fin du fichier
276
277 char ppstype;
278 size_t debut;
279#ifdef STREAMPOS_IS_CLASS
280 debut = s->tellg().offset();
281#else
282 debut = s->tellg();
283#endif
284
285 // Find tag entries at end of file
286 s->seekg(-(sizeof(int_8)+1), ios::end);
287 GetTypeTag(ppstype);
288 if (ppstype != PPS_EOF)
289 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
290
291 int_8 pos;
292 GetRawI8(pos);
293 if (pos < 0) { // no tags
294 s->seekg(debut);
295 return;
296 }
297
298 char buffer[MAXTAGLEN+1];
299 s->seekg(pos);
300 while (true) {
301 GetTypeTag(ppstype);
302 if (ppstype == PPS_EOF) break;
303
304 if (ppstype != PPS_TAG)
305 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
306
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';
314
315 tags[buffer] = pos;
316 }
317 s->seekg(debut);
318}
319
320
321int
322PInPersist::NbTags()
323{
324 return tags.size();
325}
326
327bool
328PInPersist::GotoTag(string const& name)
329{
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);
335 objList.clear(); // $CHECK$ EA 171199
336 return(true);
337}
338
339bool
340PInPersist::GotoTagNum(int itag)
341{
342 if (itag<0 || itag >= (int)tags.size()) return false;
343 map<string, int_8>::iterator i = tags.begin();
344 for (int j=0; j<itag; j++) i++;
345 s->seekg((*i).second);
346 objList.clear(); // $CHECK$ EA 171199
347 return(true);
348}
349
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}
358
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
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
425void
426PInPersist::GetTypeTag(char& c)
427{
428 GetRawByte(c);
429 while (c == PPS_TAG_MARK) {
430 objList.clear();
431 GetRawByte(c);
432 }
433}
434
435
436void
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;
484 GetTypeTag(ppstype);
485 if (ppstype != PPS_SIMPLE + datasz)
486 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
487}
488
489void
490PInPersist::CheckArrayTag(short datasz, size_t sz)
491{
492 char ppstype;
493 GetTypeTag(ppstype);
494 size_t filesz;
495 if (sz <= 0x7fff) {
496 if (ppstype != PPS_SIMPLE_ARRAY + datasz)
497 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
498 int_2 ff;
499 GetRawI2(ff); filesz=ff;
500 } else if (sz <= 0x7fffffff) {
501 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
502 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
503 int_4 ff;
504 GetRawI4(ff); filesz=ff;
505 } else {
506 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
507 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
508 uint_8 ff;
509 GetRawU8(ff); filesz=ff;
510 }
511 if (filesz != sz)
512 throw FileFormatExc("PInPersist::CheckTag bad array size in ppersist file");
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
529PInPersist::GetR4 (r_4& result)
530{
531 CheckTag(4);
532 GetRawBytes(&result, sizeof(r_4));
533 if (bigEndian != IS_BIG_ENDIAN)
534 bswap4(&result);
535}
536
537
538void
539PInPersist::GetR4s (r_4* tab, size_t n)
540{
541 CheckArrayTag(4,n);
542 GetRawBytes(tab, n*sizeof(r_4));
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{
554 CheckTag(8);
555 GetRawBytes(&result, sizeof(r_8));
556 if (bigEndian != IS_BIG_ENDIAN)
557 bswap8(&result);
558}
559
560void
561PInPersist::GetR8s (r_8* tab, size_t n)
562{
563 CheckArrayTag(8,n);
564 GetRawBytes(tab, n*sizeof(r_8));
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{
576 CheckTag(2);
577 GetRawBytes(&result, sizeof(int_2));
578 if (bigEndian != IS_BIG_ENDIAN)
579 bswap2(&result);
580}
581
582void
583PInPersist::GetI2s (int_2* tab, size_t n)
584{
585 CheckArrayTag(2,n);
586 GetRawBytes(tab, n*sizeof(int_2));
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{
598 CheckTag(2);
599 GetRawBytes(&result, sizeof(uint_2));
600 if (bigEndian != IS_BIG_ENDIAN)
601 bswap2(&result);
602}
603
604void
605PInPersist::GetU2s (uint_2* tab, size_t n)
606{
607 CheckArrayTag(2,n);
608 GetRawBytes(tab, n*sizeof(uint_2));
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{
620 CheckTag(4);
621 GetRawBytes(&result, sizeof(int_4));
622 if (bigEndian != IS_BIG_ENDIAN)
623 bswap4(&result);
624}
625
626void
627PInPersist::GetI4s (int_4* tab, size_t n)
628{
629 CheckArrayTag(4,n);
630 GetRawBytes(tab, n*sizeof(int_4));
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{
642 CheckTag(4);
643 GetRawBytes(&result, sizeof(uint_4));
644 if (bigEndian != IS_BIG_ENDIAN)
645 bswap4(&result);
646}
647
648void
649PInPersist::GetU4s (uint_4* tab, size_t n)
650{
651 CheckArrayTag(4,n);
652 GetRawBytes(tab, n*sizeof(uint_4));
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{
665 CheckTag(8);
666 GetRawBytes(&result, sizeof(int_8));
667 if (bigEndian != IS_BIG_ENDIAN)
668 bswap8(&result);
669}
670
671void
672PInPersist::GetI8s (int_8* tab, size_t n)
673{
674 CheckArrayTag(8,n);
675 GetRawBytes(tab, n*sizeof(int_8));
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{
687 CheckTag(8);
688 GetRawBytes(&result, sizeof(uint_8));
689 if (bigEndian != IS_BIG_ENDIAN)
690 bswap8(&result);
691}
692
693void
694PInPersist::GetU8s (uint_8* tab, size_t n)
695{
696 CheckArrayTag(8,n);
697 GetRawBytes(tab, n*sizeof(uint_8));
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{
710 char ppstype;
711 GetTypeTag(ppstype);
712 if (ppstype != PPS_LINE)
713 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
714 s->getline(ptr, len, '\n');
715}
716
717void
718PInPersist::GetStr(string& str)
719{
720 char ppstype;
721 GetTypeTag(ppstype);
722 if (ppstype != PPS_STRING)
723 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
724 int_2 len;
725 GetRawI2(len);
726 char * buff = new char[len+1];
727 GetRawBytes(buff, len);
728 buff[len] = '\0';
729 str = buff;
730 delete[] buff;
731}
732
733PPersist*
734PInPersist::ReadObject()
735{
736 // Get tag
737 char ppstype;
738 GetTypeTag(ppstype);
739 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
740 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
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()) {
766 char msg[200];
767 sprintf(msg, "PInPersist::ReadObject invalid object id for reference: %d/%d",id,objList.size());
768 throw FileFormatExc(msg);
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
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
805 // Output stream creation
806 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
807
808 // Header
809 PutRawBytes("SOS-SOPHYA-PPersistFile V1 ",32);
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];
817 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
818 for(int i=l; i<32; i++) datestring[i] = ' ';
819 datestring[32] = '\0';
820 PutRawBytes(datestring, 32);
821}
822
823POutPersist::~POutPersist()
824{
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
848}
849
850
851void
852POutPersist::WriteTag(string const& name)
853{
854 if (name.length() > MAXTAGLEN)
855 throw ParmError("POutPersist::WriteTag tag name too long");
856
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
863 #ifdef STREAMPOS_IS_CLASS
864 tagPos = s->tellp().offset();
865 #else
866 tagPos = s->tellp();
867 #endif
868
869 tags[name] = tagPos;
870 PutRawByte(PPS_TAG_MARK); // This is a tag
871 objList.clear(); // $CHECK$ EA 171199
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)
893// void POutPersist::PutStr (string const&)
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
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
967POutPersist::PutByte(char c)
968{
969 PutRawByte(PPS_SIMPLE + 1);
970 PutRawBytes(&c, 1);
971}
972
973
974
975void
976POutPersist::PutBytes(void const* ptr, size_t bytes)
977{
978 PutArrayTag(1, bytes);
979 PutRawBytes(ptr, bytes);
980}
981
982void
983POutPersist::PutR4 (r_4 val)
984{
985 PutRawByte(PPS_SIMPLE + 4);
986
987 if (bigEndian != IS_BIG_ENDIAN)
988 bswap4(&val);
989
990 PutRawBytes(&val, sizeof(r_4));
991}
992
993void
994POutPersist::PutR4s (r_4 const* tab, size_t n)
995{
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 }
1007}
1008
1009void
1010POutPersist::PutR8 (r_8 val)
1011{
1012 PutRawByte(PPS_SIMPLE + 8);
1013
1014 if (bigEndian != IS_BIG_ENDIAN)
1015 bswap8(&val);
1016
1017 PutRawBytes(&val, sizeof(r_8));
1018}
1019
1020void
1021POutPersist::PutR8s (r_8 const* tab, size_t n)
1022{
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 }
1034}
1035
1036void
1037POutPersist::PutI2 (int_2 val)
1038{
1039 PutRawByte(PPS_SIMPLE + 2);
1040
1041 if (bigEndian != IS_BIG_ENDIAN)
1042 bswap2(&val);
1043
1044 PutRawBytes(&val, sizeof(int_2));
1045}
1046
1047void
1048POutPersist::PutI2s (int_2 const* tab, size_t n)
1049{
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 }
1061}
1062
1063void
1064POutPersist::PutU2 (uint_2 val)
1065{
1066 PutRawByte(PPS_SIMPLE + 2);
1067
1068 if (bigEndian != IS_BIG_ENDIAN)
1069 bswap2(&val);
1070
1071 PutRawBytes(&val, sizeof(uint_2));
1072}
1073
1074void
1075POutPersist::PutU2s (uint_2 const* tab, size_t n)
1076{
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 }
1088}
1089
1090void
1091POutPersist::PutI4 (int_4 val)
1092{
1093 PutRawByte(PPS_SIMPLE + 4);
1094
1095 if (bigEndian != IS_BIG_ENDIAN)
1096 bswap4(&val);
1097
1098 PutRawBytes(&val, sizeof(int_4));
1099}
1100
1101void
1102POutPersist::PutI4s (int_4 const* tab, size_t n)
1103{
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 }
1115}
1116
1117void
1118POutPersist::PutU4 (uint_4 val)
1119{
1120 PutRawByte(PPS_SIMPLE + 4);
1121
1122 if (bigEndian != IS_BIG_ENDIAN)
1123 bswap4(&val);
1124
1125 PutRawBytes(&val, sizeof(uint_4));
1126}
1127
1128void
1129POutPersist::PutU4s (uint_4 const* tab, size_t n)
1130{
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 }
1142}
1143
1144void
1145POutPersist::PutI8 (int_8 val)
1146{
1147 PutRawByte(PPS_SIMPLE + 8);
1148
1149 if (bigEndian != IS_BIG_ENDIAN)
1150 bswap8(&val);
1151
1152 PutRawBytes(&val, sizeof(int_8));
1153}
1154
1155void
1156POutPersist::PutI8s (int_8 const* tab, size_t n)
1157{
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 }
1169}
1170
1171void
1172POutPersist::PutU8 (uint_8 val)
1173{
1174 PutRawByte(PPS_SIMPLE + 8);
1175
1176 if (bigEndian != IS_BIG_ENDIAN)
1177 bswap8(&val);
1178
1179 PutRawBytes(&val, sizeof(uint_8));
1180}
1181
1182void
1183POutPersist::PutU8s (uint_8 const* tab, size_t n)
1184{
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 }
1196}
1197
1198void
1199POutPersist::PutStr(string const& str)
1200{
1201 PutRawByte(PPS_STRING);
1202 PutRawI2(str.length());
1203 PutRawBytes(str.c_str(), str.length());
1204}
1205
1206void
1207POutPersist::PutLine(char const* ptr, size_t len)
1208{
1209 PutRawByte(PPS_LINE);
1210
1211 if (len == 0) len = strlen(ptr);
1212 PutRawBytes(ptr, len);
1213 PutRawByte('\n');
1214}
1215
1216void
1217POutPersist::PutObject(PPersist const* obj)
1218{
1219 if (serializeNullAndRepeat(obj)) return;
1220
1221 PutRawByte(PPS_OBJECT);
1222 PutRawU8(getTypeId(typeid(*obj).name()));
1223 //PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
1224 assignObjectId(obj);
1225 obj->WriteSelf(*this);
1226}
1227
1228bool
1229POutPersist::serializeNullAndRepeat(PPersist const* x)
1230{
1231 if (x == NULL) {
1232 PutRawByte(PPS_NULL);
1233 return true;
1234 }
1235
1236 int_4 id = findObjectId(x);
1237 if (id >= 0) {
1238 PutRawByte(PPS_REFERENCE);
1239 PutRawI4(id);
1240 return true;
1241 }
1242
1243 return false;
1244}
1245
1246int_4
1247POutPersist::assignObjectId(PPersist const* x)
1248{
1249 int_4 id = objList.size();
1250 objList[x] = id;
1251 return id;
1252}
1253
1254int_4
1255POutPersist::findObjectId(PPersist const* x)
1256{
1257 ObjList::iterator i = objList.find(x);
1258 if (i == objList.end()) return -1;
1259 return (*i).second;
1260}
1261
1262
Note: See TracBrowser for help on using the repository browser.