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

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

Creation module DPC/SysTools Reza 09/04/99

File size: 27.4 KB
Line 
1#include "defs.h"
2#include <stdio.h>
3#include "peidainit.h"
4#include "ppersist.h"
5#include "dates.h"
6
7#ifndef RFIO
8#include <fstream.h>
9#endif
10
11
12#ifdef __mac__
13#include "unixmac.h"
14#include <SIOUX.h>
15#endif
16
17#if SWAP==1
18#define IS_BIG_ENDIAN 0
19#else
20#define IS_BIG_ENDIAN 1
21#endif
22
23//++
24// Class PPersistMgr
25// Lib Outils++
26// include ppersist.h
27//
28// Classe gestionnaire d'objets persistants. Les méthodes statiques
29// de cette classe permettent d'enregistrer des classes persistantes,
30// et de relire automatiquement des objets.
31//--
32
33//++
34// Links Voir
35// PPersist
36// PShPersist
37//--
38
39PPersistMgr::ClassList* PPersistMgr::classList = NULL;
40PShPersist::ObjList* PShPersist::objList = NULL;
41
42//++
43void
44PPersistMgr::RegisterClass(int_4 classId, ClassCreatorFunc f, bool shared)
45//
46// Enregistre une nouvelle classe auprès du gestionnaire. classId doit
47// identifier de façon unique la classe. f doit créer un nouvel objet
48// de cette classe (qui doit hériter de PPersist), non initialisé, et qui
49// sera relu à partir du fichier d'objets persistants.
50//
51// Si shared est true, la classe doit hériter de PShPersist, et la persistance
52// gère le fait que plusieurs objets Xi puissent faire référence à un même objet A.
53// A, qui hérite donc de PShPersist, ne sera écrit qu'une seule fois dans le fichier
54// lorsque les Xi sont écrits, et la référence à A sera mise à jour lors de la lecture
55// des Xi...
56//--
57{
58 DBASSERT(classList);
59 if (classList->size() && (classList->find(classId) != classList->end())) {
60 cerr << "RegisterClass : Error, " << hex << classId << dec
61 << " already registered." << endl;
62 THROW(dupIdErr);
63 }
64
65 ClassListEntry entry = {shared, f};
66 (*classList)[classId] = entry;
67}
68
69
70PPersistMgr::ClassCreatorFunc
71PPersistMgr::FindCreatorFunc(int_4 classId)
72{
73 DBASSERT(classList);
74 return (*classList)[classId].f;
75}
76
77PPersistMgr::ClassCreatorFunc
78PPersistMgr::FindCreatorFunc(int_4 classId, bool& isShared)
79{
80 DBASSERT(classList);
81 ClassListEntry entry = (*classList)[classId];
82 isShared = entry.shared;
83 return entry.f;
84}
85
86//++
87PPersist*
88PPersistMgr::ReadObject(PInPersist& s)
89//
90// Lit un objet dans le stream s, en créant automatiquement un
91// objet du bon type.
92//--
93{
94 DBASSERT(classList);
95 DBASSERT(PShPersist::objList);
96 // On commence par lire le type de l'objet
97 int_4 classId;
98 s >> classId;
99
100 // On recupere le createur, et on regarde si l'objet est partage
101 bool shared;
102 if (!classList->size() || (classList->find(classId) == classList->end())) {
103 cerr << "PPersistMgr::ReadObject Error : Class " << classId << " not registered" << endl;
104 THROW(notFoundErr);
105 }
106 PPersistMgr::ClassCreatorFunc f = FindCreatorFunc(classId, shared);
107
108 if (!f) THROW(notFoundErr);
109
110 PPersist* object;
111 if (shared) {
112 // Si l'objet est partage, ce qui suit est son identificateur, sur 4 octets
113 // et un octet ensuite qui dit si l'objet est present.
114
115 int_4 objectId;
116 char objectSaved;
117
118 s >> objectId >> objectSaved;
119
120#if 0
121 // On regarde si l'objet est deja en memoire
122 object = PShPersist::FindObject(objectId);
123
124 // On verifie qu'on est dans une situation coherente...
125 if ((!objectSaved) == (!object)) THROW(inconsistentErr);
126#else
127 if (!objectSaved) {
128 object = PShPersist::FindObject(objectId);
129 if (!object) THROW(inconsistentErr);
130 }
131#endif
132 if (objectSaved) {
133 object = f();
134 object->ReadSelf(s);
135 ((PShPersist*)object)->mObjectID = objectId;
136 (*PShPersist::objList)[objectId] = (PShPersist*)object;
137 }
138 } else {
139 object = f();
140 object->ReadSelf(s);
141 }
142
143 return object;
144}
145
146//++
147// Class PPersist
148// Lib Outils++
149// include ppersist.h
150//
151// Classe de base pour des objets persistants. Pour créer un objet
152// persistant :
153// - Hériter de PPersist.
154// - Définir un numéro d'identification de la classe, unique dans Peida
155// - Implémenter "ClassId()"
156// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
157// membres que l'on souhaite écrire, et les relire dans le même ordre.
158// Pour écrire une référence à un objet : l'objet doit être un PPersist,
159// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
160// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
161// fois, il faut que cet objet soit un PShPersist.
162// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
163// les fonctions PutXX/GetXX de PInPersist/POutPersist.
164//
165// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
166// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
167//--
168
169//++
170// Links Voir
171// PInPersist
172// POutPersist
173// PPersistMgr
174// PShPersist
175//--
176
177PShPersist*
178PShPersist::FindObject(int_4 objId)
179{
180 DBASSERT(objList);
181 return (*objList)[objId];
182}
183
184//++
185void
186PPersist::Write(string const& fn) const
187//
188// Ecrit l'objet dans un nouveau fichier ppersist "fn".
189//--
190{
191 POutPersist of(fn);
192 Write(of);
193}
194
195//++
196void
197PPersist::Read(string const& fn)
198//
199// Relit l'objet dans le fichier ppersist "fn". Il faut connaître a priori
200// le type de l'objet. Pour une relecture avec création automatique du bon
201// objet, utiliser PPersistMgr::ReadObject.
202//--
203{
204 PInPersist inf(fn);
205 Read(inf);
206}
207
208//++
209void
210PPersist::Write(POutPersist& s) const
211//
212// Ecrit l'objet dans le fichier PPersist.
213//--
214{
215 // On doit tout d'abord ecrire notre type
216 s << ClassId();
217 // Puis on s'ecrit, tout betement...
218 WriteSelf(s);
219}
220
221
222//++
223void
224PPersist::Read(PInPersist& s)
225//
226// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
227// le type de l'objet. Pour une relecture avec création automatique du bon
228// objet, utiliser PPersistMgr::ReadObject.
229//--
230{
231 // A n'utiliser que si on connait a priori
232 // le vrai type de l'objet.
233
234 // On doit tout d'abord lire notre type
235 int_4 classId;
236 s >> classId;
237 if (classId != ClassId()) {
238 cerr << "PPersist::Read() Object type (=" << ClassId() << ") mismatch (type in file="
239 << classId << ")" << endl;
240 THROW(typeMismatchErr); }
241 // Puis on se lit, tout betement...
242
243 ReadSelf(s);
244}
245
246//++
247int_4
248PPersist::Write(POutPersist& s, int_4 key) const
249//
250// Ecrit l'objet dans le fichier PPersist avec un tag ayant "key" comme
251// valeur du champ clé du tag.
252//--
253{
254 int_4 rc;
255 // On ecrit le tag de positionnement et on recupere le numero de tag
256 rc = s.WriteTag(key, NULL);
257 // avant d'ecrire l'objet lui-meme
258 Write(s);
259 return(rc);
260}
261
262//++
263int_4
264PPersist::Write(POutPersist& s, int_4 key, string& nom) const
265//
266// Ecrit l'objet dans le fichier PPersist avec un tag ayant "key", nom comme
267// valeurs des champs clé et nom du tag.
268//--
269{
270 int_4 rc;
271 // On ecrit le tag de positionnement et on recupere le numero de tag
272 rc = s.WriteTag(key, nom.c_str());
273 // avant d'ecrire l'objet lui-meme
274 Write(s);
275 return(rc);
276}
277
278//++
279void
280PPersist::ReadAtTag(PInPersist& s, int_4 tagid)
281//
282// Lit l'objet à la position du tag numéro "tagid".
283//--
284{
285 if (s.GotoTag(tagid)) Read(s);
286 else {
287 cerr << "PInPersist::GotoTag() Error ! \n" <<
288 "From PPersist::ReadAtTag(PInPersist, tag= " << tagid << ") " << endl;
289 THROW(fileErr);
290 }
291 return;
292}
293
294//++
295void
296PPersist::ReadAtKey(PInPersist& s, int_4 key)
297//
298// Lit l'objet à la position du tag contenant la clé "key".
299//--
300{
301 if (s.GotoKey(key)) Read(s);
302 else {
303 cerr << "PInPersist::GotoKey() Error ! \n" <<
304 "From PPersist::ReadAtKey(PInPersist, key= " << key << ") " << endl;
305 THROW(fileErr);
306 }
307 return;
308}
309
310//++
311// virtual void PPersist::ReadSelf(PInPersist&)=0
312// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
313// et PPersistMgr::ReadObject. Il faut relire les variables membres,
314// dans l'ordre où elles ont été écrites par WriteSelf.
315// virtual void PPersist::WriteSelf(POutPersist&) const=0
316// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
317// Il faut écrire les variables membres,
318// dans l'ordre où elles seront relues par ReadSelf.
319//--
320
321
322//++
323// Class PShPersist
324// Lib Outils++
325// include ppersist.h
326//
327// Classe de base pour des objets persistants partagés.
328// Un tel objet ne sera écrit qu'une seule fois dans un fichier
329// donné. Les tentatives suivantes d'écriture n'écrivent qu'une
330// référence à la première écriture.
331//
332// Lors de la lecture, l'objet est créé lors de la première lecture,
333// puis l'adresse de cet objet est retournée lors des lectures suivantes.
334//--
335
336//++
337// Links Parents
338// PPersist
339//--
340
341//++
342void
343PShPersist::Write(POutPersist& s) const
344//
345// Ecrit l'objet dans le fichier s.
346//
347// En fait, l'objet est physiquement écrit une seule fois.
348//--
349{
350 DBASSERT(objList);
351 // On doit tout d'abord ecrire notre type
352
353 s << ClassId();
354
355 // On doit ensuite ecrire notre identificateur et le flag d'ecriture
356
357 char write = (mObjectID == 0) ? 255 : 0;
358 if (mObjectID == 0) {
359 (int_4&)mObjectID = (*objList).size() ? (*((*objList).rbegin())).first+1 : 1;
360 (*objList)[mObjectID] = (PShPersist*)this;
361 }
362
363 s << mObjectID << write ;
364
365 // Puis, si necessaire, on s'ecrit
366
367 if (write)
368 WriteSelf(s);
369}
370
371PShPersist::~PShPersist() // Une securite peut-etre facultative
372{
373 DBASSERT(objList);
374 if (mObjectID) {
375 DBASSERT(!objList->size() && (objList->find(mObjectID) != objList->end()));
376 objList->erase(mObjectID);
377 }
378}
379
380void
381PPersistMgr::Reset()
382{
383 DBASSERT(PShPersist::objList);
384 for (PShPersist::ObjList::iterator i = PShPersist::objList->begin();
385 i != PShPersist::objList->end(); i++)
386 (*i).second->mObjectID = 0; // Une securite peut-etre facultative
387
388 PShPersist::objList->erase(PShPersist::objList->begin(), PShPersist::objList->end());
389}
390
391#define PIOP_Delim '\n' // Delimiteur de ligne
392// Les noms ne peuvent depasser 255 caracteres
393#define MAXTAGNAMELEN 255
394
395//++
396// Class PInPersist
397// Lib Outils++
398// include ppersist.h
399//
400// Fichier d'objets persistants, en lecture.
401//--
402
403//++
404PInPersist::PInPersist(string const& flnm, bool scan)
405//
406// Constructeur. Ouvre le fichier.
407//--
408{
409 mSbsz = 0; // Pour conserver les noms des tags ( V4 et au dela )
410 mSbuf = NULL;
411 mTags = NULL;
412 mNTags = 0; // " " " "
413 fName = flnm;
414#ifdef RFIO
415 s = new erosifstream(flnm.c_str(),"rb");
416#else
417// $CHECK$ EA ios::binary (ou ios::bin) doit exister PARTOUT.
418// Voir note dans defs.h pres de HAS_IOS_BIN
419#if defined(__MWERKS__)
420 s = new ifstream(flnm.c_str(),ios::in | ios::binary); // ios::binary pas connnu partout - $CHECK$ Reza 13/02/98
421#else
422 s = new ifstream(flnm.c_str(),ios::in );
423#endif
424#endif
425 PPersistMgr::Reset();
426 char rbuf[36];
427 GetBytes(rbuf, 32);
428 if (strncmp(rbuf,"PEIDA-PPersistFile", 18) != 0) {
429 cerr << "PInPersist::PInPersist Error : File " << flnm << " (empty file or bad header)"
430 << endl;
431 THROW(fileErr); }
432 version = atoi(rbuf+20);
433 bigEndian = IS_BIG_ENDIAN; // Les V2 sont relus en mode natif
434 if (version >= 3) {
435 GetBytes(rbuf, 32);
436 if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
437 bigEndian = true;
438 else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
439 bigEndian = false;
440 else {
441 cerr << "PInPersist::PInPersist Error : File" << flnm;
442 cerr << " (V>=3 et ni BIG-ENDIAN, ni LITTLE-ENDIAN" << endl;
443 THROW(fileErr);
444 }
445 }
446 if (version >= 5) { // On lit la date de creation (V5 et au-dela)
447 GetBytes(rbuf, 32);
448 rbuf[32] = '\0';
449 for(int k=0; k<32; k++)
450 if (rbuf[k] == ' ') { rbuf[k] = '\0'; break; }
451 creationdate = rbuf;
452 } // Fin de lecture de date
453 else creationdate = "??/??/??" ;
454 // Le fichier peut contenir des tag (V4 et au dela)
455 if ( (version >= 4) && scan ) Scan();
456}
457
458
459
460PInPersist::~PInPersist()
461{
462 list<char*>::iterator it;
463 for(it = mSbuffs.begin(); it != mSbuffs.end(); it++) delete[] (*it);
464 if (mTags) delete[] mTags;
465 delete s;
466 PPersistMgr::Reset();
467}
468
469// A cause de aCC qui ne veut pas char* b = ""
470static char ChaineVide[2] = {'\0', '\0'};
471
472void
473PInPersist::Scan()
474{
475// On parcourt le fichier depuis la fin pour identifier tous les tags
476 int_8 debut, prev, premier;
477 int_4 ntag, ntc, ll;
478 uint_2 ln;
479 char pad[4];
480
481 #if defined(STREAMPOS_IS_CLASS) && !defined(RFIO)
482 debut = s->tellg().offset();
483 #else
484 debut = s->tellg();
485 #endif
486
487 premier = 0;
488 s->seekg(-(sizeof(int_8)+sizeof(int_4)), ios::end);
489 GetI8(prev);
490 GetI4(ntag);
491 if ( (ntag <= 0) || (prev < 0) )
492 { s->seekg(debut,ios::beg); return; }
493
494 mNTags = ntag;
495 mTags = new PPFTag[ntag];
496
497 PPFTag* tag;
498 while( (prev > 0) && (ntag > 0) ) {
499 s->seekg(prev);
500 if (ntag == 1) premier = prev;
501 GetI8(prev);
502 GetI4(ntc);
503 ntag--;
504 if (ntc != ntag) {
505 cerr << "PInPersist::Scan() / Error: NTag,TC= " << ntag << "," << ntc << endl;
506 THROW(fileErr);
507 }
508 tag = mTags+ntag;
509 GetI4(tag->key);
510 GetU2(ln);
511 if (ln > 0) {
512 tag->lnom = ln;
513 tag->nom = GetCStr(ln);
514 GetBytes(tag->nom, ln+1);
515 ll = 3-((ln+2)%4);
516 GetBytes(pad, ll);
517 }
518 else {
519 GetU2(ln);
520 tag->lnom = 0;
521 tag->nom = ChaineVide;
522 }
523// On recupere la position pour l'objet qui suit
524 #ifdef STREAMPOS_IS_CLASS
525 tag->popos = s->tellg().offset();
526 #else
527 tag->popos = s->tellg();
528 #endif
529
530 GetI4(tag->cid);
531 }
532
533 if ( (ntag != 0) || (prev >= 0) ) { // En principe , ca ne doit pas arriver
534 cerr << "PInPersist::Scan() / Error: (End: ntag=" << ntag <<
535 " prev=" << (int_4)prev << endl;
536 THROW(fileErr);
537 }
538// on se repositionne au debut du 1er objet du fichier
539 if (premier == debut) GotoTag(0);
540 else s->seekg(debut);
541 return;
542}
543
544char*
545PInPersist::GetCStr(uint_2 sz)
546{
547char* rs;
548sz += 1; // Pour le 0 de la fin
549if (sz > mSbsz)
550 { mSbsz = (sz > (MAXTAGNAMELEN+1)) ? sz : (MAXTAGNAMELEN+1);
551 mSbuf = new char[mSbsz]; mSbuffs.push_back(mSbuf); }
552
553rs = mSbuf;
554mSbuf += sz;
555mSbsz -= sz;
556return(rs);
557}
558
559bool
560PInPersist::GotoTag(int_4 num)
561{
562 if ( (num < 0) || (num >= mNTags) ) return(false);
563 s->seekg(mTags[num].popos);
564 return(true);
565}
566
567bool
568PInPersist::GotoKey(int_4 key, int rang)
569{
570 if (rang < 0) return(false);
571 int n = 0, i;
572 int fnd = -1;
573 for(i=0; i<mNTags; i++)
574 if (mTags[i].key == key) {
575 if (n == rang) { fnd = i; break; }
576 n++; }
577
578 if (fnd >= 0) return(GotoTag(fnd));
579 else return(false);
580}
581
582int
583PInPersist::NbKey(int_4 key)
584{
585 int n = 0, i;
586 for(i=0; i<mNTags; i++)
587 if (mTags[i].key == key) n++;
588 return(n);
589}
590
591void
592PInPersist::ListTags()
593{
594 cout << "PInPersist/ File " << fName << "\n";
595 cout << "Nb Tags in file : " << mNTags << "\n";
596 string str;
597 int i;
598 for(i=0; i<mNTags; i++) {
599 str = mTags[i].nom;
600 cout << i << "- CId= " << mTags[i].cid << " Key= "
601 << mTags[i].key << " ( " << str << " )\n" ;
602 }
603 cout << endl;
604 return;
605}
606
607int_4
608PInPersist::TagKey(int_4 num, int_4& cid, int_4& ln)
609{
610 if ( (num < 0) || (num >= mNTags) ) return(0);
611 cid = mTags[num].cid; ln = mTags[num].lnom;
612 return(mTags[num].key);
613}
614
615string
616PInPersist::TagName(int_4 num)
617{
618 if ( (num < 0) || (num >= mNTags) ) return("");
619 return((string)mTags[num].nom);
620}
621
622//++
623// void PInPersist::GetByte(char& c)
624// void PInPersist::GetBytes(void* ptr, size_t bytes)
625// void PInPersist::GetR4 (r_4& result)
626// void PInPersist::GetR4s (r_4* tab, size_t n)
627// void PInPersist::GetR8 (r_8& result)
628// void PInPersist::GetR8s (r_8* tab, size_t n)
629// void PInPersist::GetI2 (int_2& result)
630// void PInPersist::GetI2s (int_2* tab, size_t n)
631// void PInPersist::GetU2 (uint_2& result)
632// void PInPersist::GetU2s (uint_2* tab, size_t n)
633// void PInPersist::GetI4 (int_4& result)
634// void PInPersist::GetI4s (int_4* tab, size_t n)
635// void PInPersist::GetU4 (uint_4& result)
636// void PInPersist::GetU4s (uint_4* tab, size_t n)
637// void PInPersist::GetI8 (int_8& result)
638// void PInPersist::GetI8s (int_8* tab, size_t n)
639// void PInPersist::GetU8 (uint_8& result)
640// void PInPersist::GetU8s (uint_8* tab, size_t n)
641// Lecture de données portables depuis le fichier PPersist. Pour chaque type
642// de données, on peut lire une valeur, ou un tableau de valeurs.
643// void PInPersist::GetLine(char* ptr, size_t len)
644// Lecture d'une ligne de texte depuis le fichier PPersist.
645//--
646
647void
648PInPersist::GetByte(char& c)
649{
650 GetBytes(&c, 1);
651}
652
653void
654PInPersist::GetBytes(void* ptr, size_t bytes)
655{
656 s->read((char*)ptr, bytes);
657}
658
659static inline void bswap8(void* p)
660{
661 uint_8 tmp = *(uint_8*)p;
662 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
663 ((tmp >> (5*8)) & 0x0000FF00) |
664 ((tmp >> (3*8)) & 0x00FF0000) |
665 ((tmp >> (1*8)) & 0xFF000000) |
666 ((tmp & 0xFF000000) << (1*8)) |
667 ((tmp & 0x00FF0000) << (3*8)) |
668 ((tmp & 0x0000FF00) << (5*8)) |
669 ((tmp & 0x000000FF) << (7*8));
670}
671
672static inline void bswap4(void* p)
673{
674 uint_4 tmp = *(uint_4*)p;
675 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
676 ((tmp >> 8) & 0x0000FF00) |
677 ((tmp & 0x0000FF00) << 8) |
678 ((tmp & 0x000000FF) << 24);
679}
680
681static inline void bswap2(void* p)
682{
683 uint_2 tmp = *(uint_2*)p;
684 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
685 ((tmp & 0x00FF) << 8);
686}
687
688void
689PInPersist::GetR4 (r_4& result)
690{
691 GetBytes(&result, sizeof(r_4));
692 if (bigEndian != IS_BIG_ENDIAN)
693 bswap4(&result);
694}
695
696
697void
698PInPersist::GetR4s (r_4* tab, size_t n)
699{
700 GetBytes(tab, n*sizeof(r_4));
701 if (bigEndian == IS_BIG_ENDIAN) return;
702
703 for (unsigned int i=0; i<n; i++)
704 bswap4(tab+i);
705
706 return;
707}
708
709void
710PInPersist::GetR8 (r_8& result)
711{
712 GetBytes(&result, sizeof(r_8));
713 if (bigEndian != IS_BIG_ENDIAN)
714 bswap8(&result);
715}
716
717void
718PInPersist::GetR8s (r_8* tab, size_t n)
719{
720 GetBytes(tab, n*sizeof(r_8));
721 if (bigEndian == IS_BIG_ENDIAN) return;
722
723 for (unsigned int i=0; i<n; i++)
724 bswap8(tab+i);
725
726 return;
727}
728
729void
730PInPersist::GetI2 (int_2& result)
731{
732 GetBytes(&result, sizeof(int_2));
733 if (bigEndian != IS_BIG_ENDIAN)
734 bswap2(&result);
735}
736
737void
738PInPersist::GetI2s (int_2* tab, size_t n)
739{
740 GetBytes(tab, n*sizeof(int_2));
741 if (bigEndian == IS_BIG_ENDIAN) return;
742
743 for (unsigned int i=0; i<n; i++)
744 bswap2(tab+i);
745
746 return;
747}
748
749void
750PInPersist::GetU2 (uint_2& result)
751{
752 GetBytes(&result, sizeof(uint_2));
753 if (bigEndian != IS_BIG_ENDIAN)
754 bswap2(&result);
755}
756
757void
758PInPersist::GetU2s (uint_2* tab, size_t n)
759{
760 GetBytes(tab, n*sizeof(uint_2));
761 if (bigEndian == IS_BIG_ENDIAN) return;
762
763 for (unsigned int i=0; i<n; i++)
764 bswap2(tab+i);
765
766 return;
767}
768
769void
770PInPersist::GetI4 (int_4& result)
771{
772 GetBytes(&result, sizeof(int_4));
773 if (bigEndian != IS_BIG_ENDIAN)
774 bswap4(&result);
775}
776
777void
778PInPersist::GetI4s (int_4* tab, size_t n)
779{
780 GetBytes(tab, n*sizeof(int_4));
781 if (bigEndian == IS_BIG_ENDIAN) return;
782
783 for (unsigned int i=0; i<n; i++)
784 bswap4(tab+i);
785
786 return;
787}
788
789void
790PInPersist::GetU4 (uint_4& result)
791{
792 GetBytes(&result, sizeof(uint_4));
793 if (bigEndian != IS_BIG_ENDIAN)
794 bswap4(&result);
795}
796
797void
798PInPersist::GetU4s (uint_4* tab, size_t n)
799{
800 GetBytes(tab, n*sizeof(uint_4));
801 if (bigEndian == IS_BIG_ENDIAN) return;
802
803 for (unsigned int i=0; i<n; i++)
804 bswap4(tab+i);
805
806 return;
807}
808
809
810void
811PInPersist::GetI8 (int_8& result)
812{
813 GetBytes(&result, sizeof(int_8));
814 if (bigEndian != IS_BIG_ENDIAN)
815 bswap8(&result);
816}
817
818void
819PInPersist::GetI8s (int_8* tab, size_t n)
820{
821 GetBytes(tab, n*sizeof(int_8));
822 if (bigEndian == IS_BIG_ENDIAN) return;
823
824 for (unsigned int i=0; i<n; i++)
825 bswap8(tab+i);
826
827 return;
828}
829
830void
831PInPersist::GetU8 (uint_8& result)
832{
833 GetBytes(&result, sizeof(uint_8));
834 if (bigEndian != IS_BIG_ENDIAN)
835 bswap8(&result);
836}
837
838void
839PInPersist::GetU8s (uint_8* tab, size_t n)
840{
841 GetBytes(tab, n*sizeof(uint_8));
842 if (bigEndian == IS_BIG_ENDIAN) return;
843
844 for (unsigned int i=0; i<n; i++)
845 bswap8(tab+i);
846
847 return;
848}
849
850
851void
852PInPersist::GetLine(char* ptr, size_t len)
853{
854 s->getline(ptr, len, PIOP_Delim);
855}
856
857
858//++
859// Class POutPersist
860// Lib Outils++
861// include ppersist.h
862//
863// Fichier d'objets persistants, en écriture.
864//--
865
866
867//++
868// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
869//
870// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
871// sur machines petit-boutiennes, et gros-boutien sur machines
872// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
873// ou PPersist::PPS_BIG_ENDIAN.
874//--
875POutPersist::POutPersist(string const& flnm, int endianness)
876{
877 if (endianness == -1)
878 bigEndian = IS_BIG_ENDIAN;
879 else
880 bigEndian = endianness;
881
882#ifdef RFIO
883 s = new erosofstream(flnm.c_str(),"wb");
884#else
885#if defined(__MWERKS__)
886 s = new ofstream(flnm.c_str(),ios::out | ios::binary); // ios::binary pas connnu partout - $CHECK$ Reza 13/02/98
887#else
888 s = new ofstream(flnm.c_str(),ios::out );
889#endif
890#endif
891 PPersistMgr::Reset();
892 PutBytes("PEIDA-PPersistFile V5 ",32);
893 PutBytes(bigEndian
894 ? "BIG-ENDIAN "
895 : "LITTLE-ENDIAN ",32);
896// ---- On ecrit la date de creation a partir de V5
897 Date today;
898 string stod = today.DateStr(Date::kLocalTime) + "#" + today.TimeStr(Date::kLocalTime);
899 char buff[36];
900 int l = stod.length();
901 if (l < 33) strcpy(buff, stod.c_str());
902 else strncpy(buff, stod.c_str(), 33);
903 for(int i=l+1; i<32; i++) buff[i] = ' ';
904 buff[32] = '\0';
905 PutBytes(buff, 32);
906// Fin d'ecriture de date --------
907 previous = -1; // Pas de Tag precedant
908 numTag = 0;
909}
910
911POutPersist::~POutPersist()
912{
913 PutI8(previous);
914 PutI4(numTag);
915 delete s;
916 PPersistMgr::Reset();
917}
918
919
920int_4
921POutPersist::WriteTag(int_4 key, char const * nom)
922{
923 int_8 nexprev;
924 uint_2 l;
925 int ll;
926 char pad[4] = {'\0', '\0', '\0', '\0'};
927
928 #ifdef STREAMPOS_IS_CLASS
929 nexprev = s->tellp().offset();
930 #else
931 nexprev = s->tellp();
932 #endif
933// On ecrit dans l'ordre
934// - La position du tag precedant (-1 s'il n'y en a pas)
935// - Le numero de tag ( qui s incremete automatiquement )
936// - La cle utilisateur (key)
937// - La longueur du nom
938// - le nom lui-meme (Avec un pad afin de faire nom+longueur=multiple de 4)
939 PutI8(previous);
940 PutI4(numTag);
941 PutI4(key);
942 if (nom==NULL) {
943 PutU2(0); PutU2(0);
944 }
945 else {
946 ll = strlen(nom);
947 if (ll <= 0) {
948 PutU2(0); PutU2(0);
949 }
950 l = (ll <= MAXTAGNAMELEN) ? ll : MAXTAGNAMELEN ;
951 PutU2(l);
952 PutBytes(nom,l+1);
953 ll = 3-((ll+2)%4);
954 PutBytes(pad, ll);
955 }
956 previous = nexprev;
957 numTag++;
958 return((numTag-1));
959}
960
961//++
962// void POutPersist::PutByte(char& c)
963// void POutPersist::PutBytes(void const* ptr, size_t bytes)
964// void POutPersist::PutR4 (r_4 result)
965// void POutPersist::PutR4s (r_4 const* tab, size_t n)
966// void POutPersist::PutR8 (r_8 result)
967// void POutPersist::PutR8s (r_8 const* tab, size_t n)
968// void POutPersist::PutI2 (int_2 result)
969// void POutPersist::PutI2s (int_2 const* tab, size_t n)
970// void POutPersist::PutU2 (uint_2 result)
971// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
972// void POutPersist::PutI4 (int_4 result)
973// void POutPersist::PutI4s (int_4 const* tab, size_t n)
974// void POutPersist::PutU4 (uint_4 result)
975// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
976// void POutPersist::PutI8 (int_8 result)
977// void POutPersist::PutI8s (int_8 const* tab, size_t n)
978// void POutPersist::PutU8 (uint_8 result)
979// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
980// Ecriture de données portables.. Pour chaque type
981// de données, on peut écrire une valeur, ou un tableau de valeurs.
982// void POutPersist::PutLine(char const* ptr, size_t len)
983// Ecriture d'une ligne de texte dans le fichier PPersist.
984//--
985
986
987
988
989void
990POutPersist::PutByte(char c)
991{
992 PutBytes(&c, 1);
993}
994
995void
996POutPersist::PutBytes(void const* ptr, size_t bytes)
997{
998 s->write((char const*)ptr, bytes);
999}
1000
1001void
1002POutPersist::PutR4 (r_4 val)
1003{
1004 if (bigEndian != IS_BIG_ENDIAN)
1005 bswap4(&val);
1006
1007 PutBytes(&val, sizeof(r_4));
1008}
1009
1010void
1011POutPersist::PutR4s (r_4 const* tab, size_t n)
1012{
1013 if (bigEndian == IS_BIG_ENDIAN)
1014 PutBytes(tab, n*sizeof(r_4));
1015 else
1016 for (unsigned int i=0; i<n; i++)
1017 PutR4(tab[i]);
1018}
1019
1020void
1021POutPersist::PutR8 (r_8 val)
1022{
1023 if (bigEndian != IS_BIG_ENDIAN)
1024 bswap8(&val);
1025
1026 PutBytes(&val, sizeof(r_8));
1027}
1028
1029void
1030POutPersist::PutR8s (r_8 const* tab, size_t n)
1031{
1032 if (bigEndian == IS_BIG_ENDIAN)
1033 PutBytes(tab, n*sizeof(r_8));
1034 else
1035 for (unsigned int i=0; i<n; i++)
1036 PutR8(tab[i]);
1037}
1038
1039void
1040POutPersist::PutI2 (int_2 val)
1041{
1042 if (bigEndian != IS_BIG_ENDIAN)
1043 bswap2(&val);
1044
1045 PutBytes(&val, sizeof(int_2));
1046}
1047
1048void
1049POutPersist::PutI2s (int_2 const* tab, size_t n)
1050{
1051 if (bigEndian == IS_BIG_ENDIAN)
1052 PutBytes(tab, n*sizeof(int_2));
1053 else
1054 for (unsigned int i=0; i<n; i++)
1055 PutI2(tab[i]);
1056}
1057
1058void
1059POutPersist::PutU2 (uint_2 val)
1060{
1061 if (bigEndian != IS_BIG_ENDIAN)
1062 bswap2(&val);
1063
1064 PutBytes(&val, sizeof(uint_2));
1065}
1066
1067void
1068POutPersist::PutU2s (uint_2 const* tab, size_t n)
1069{
1070 if (bigEndian == IS_BIG_ENDIAN)
1071 PutBytes(tab, n*sizeof(uint_2));
1072 else
1073 for (unsigned int i=0; i<n; i++)
1074 PutU2(tab[i]);
1075}
1076
1077void
1078POutPersist::PutI4 (int_4 val)
1079{
1080 if (bigEndian != IS_BIG_ENDIAN)
1081 bswap4(&val);
1082
1083 PutBytes(&val, sizeof(int_4));
1084}
1085
1086void
1087POutPersist::PutI4s (int_4 const* tab, size_t n)
1088{
1089 if (bigEndian == IS_BIG_ENDIAN)
1090 PutBytes(tab, n*sizeof(int_4));
1091 else
1092 for (unsigned int i=0; i<n; i++)
1093 PutI4(tab[i]);
1094}
1095
1096void
1097POutPersist::PutU4 (uint_4 val)
1098{
1099 if (bigEndian != IS_BIG_ENDIAN)
1100 bswap4(&val);
1101
1102 PutBytes(&val, sizeof(uint_4));
1103}
1104
1105void
1106POutPersist::PutU4s (uint_4 const* tab, size_t n)
1107{
1108 if (bigEndian == IS_BIG_ENDIAN)
1109 PutBytes(tab, n*sizeof(uint_4));
1110 else
1111 for (unsigned int i=0; i<n; i++)
1112 PutU4(tab[i]);
1113}
1114
1115void
1116POutPersist::PutI8 (int_8 val)
1117{
1118 if (bigEndian != IS_BIG_ENDIAN)
1119 bswap8(&val);
1120
1121 PutBytes(&val, sizeof(int_8));
1122}
1123
1124void
1125POutPersist::PutI8s (int_8 const* tab, size_t n)
1126{
1127 if (bigEndian == IS_BIG_ENDIAN)
1128 PutBytes(tab, n*sizeof(int_8));
1129 else
1130 for (unsigned int i=0; i<n; i++)
1131 PutI8(tab[i]);
1132}
1133
1134void
1135POutPersist::PutU8 (uint_8 val)
1136{
1137 if (bigEndian != IS_BIG_ENDIAN)
1138 bswap8(&val);
1139
1140 PutBytes(&val, sizeof(uint_8));
1141}
1142
1143void
1144POutPersist::PutU8s (uint_8 const* tab, size_t n)
1145{
1146 if (bigEndian == IS_BIG_ENDIAN)
1147 PutBytes(tab, n*sizeof(uint_8));
1148 else
1149 for (unsigned int i=0; i<n; i++)
1150 PutU8(tab[i]);
1151}
1152
1153void
1154POutPersist::PutLine(char const* ptr, size_t len)
1155{
1156 if (len == 0) len = strlen(ptr);
1157 s->write(ptr, len);
1158#ifdef RFIO
1159 char cd = PIOP_Delim;
1160 s->write(&cd, 1);
1161#else
1162 s->put(PIOP_Delim);
1163#endif
1164
1165}
1166
1167
1168// --- Classe d'initialisation de PEIDA++, (PPersistMgr en particulier)
1169int PeidaInitiator::FgInit = 0;
1170
1171PeidaInitiator::PeidaInitiator()
1172{
1173 FgInit++;
1174 if (FgInit > 1) return;
1175
1176 InitFailNewHandler();
1177
1178 #ifdef xx__mac__
1179 //InitToolBox();
1180 //SIOUXSettings.initializeTB = FALSE;
1181 SIOUXSettings.autocloseonquit = FALSE;
1182 SIOUXSettings.asktosaveonclose = FALSE;
1183 SIOUXSettings.showstatusline = TRUE;
1184 #endif
1185
1186 PPersistMgr::classList = new PPersistMgr::ClassList;
1187 PShPersist::objList = new PShPersist::ObjList;
1188
1189
1190#if (!defined(__GNUG__) && !defined(__MWERKS__) && !defined(HPUX))
1191 // pas de bufferisation pour printf cmv 18/3/97 selon E.A.
1192 // setvbuf(stdout,NULL,_IOLBF,0); setvbuf(stderr,NULL,_IOLBF,0);
1193 setlinebuf(stdout);
1194 setlinebuf(stderr);
1195#endif
1196
1197 // si var env PEIDA_NOPRTVER definie pas de print
1198 if(!getenv("PEIDA_NOPRTVER")) PrintPeidaVersion();
1199}
1200
1201PeidaInitiator::~PeidaInitiator()
1202{
1203 FgInit--;
1204 if (FgInit == 0)
1205 {
1206 delete PPersistMgr::classList; PPersistMgr::classList = NULL;
1207 delete PShPersist::objList; PShPersist::objList = NULL;
1208 }
1209}
1210
1211double PeidaInitiator::Version(bool fgprt)
1212{
1213if (fgprt) PrintPeidaVersion();
1214return(PeidaVersion());
1215}
1216
1217// On met un objet initiator en statique, pour les loaders qui savent
1218// appeler le constructeur des objets statiques Reza 08/98
1219static PeidaInitiator ppeidainit;
1220
Note: See TracBrowser for help on using the repository browser.