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

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

Preparation pour tag V_Oct99 , Reza 29/11/99

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