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

Last change on this file since 743 was 742, checked in by ansari, 26 years ago

new md5

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