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
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_CONTEXT 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 #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
260 creationdate = mktime(&tm);
261
262 if (scan) Scan();
263}
264
265
266
267PInPersist::~PInPersist()
268{
269 delete s;
270}
271
272
273void
274PInPersist::Scan()
275{
276 // On cherche la liste des tags, a la fin du fichier
277
278 char ppstype;
279 size_t debut;
280#ifdef STREAMPOS_IS_CLASS
281 debut = s->tellg().offset();
282#else
283 debut = s->tellg();
284#endif
285
286 // Find tag entries at end of file
287 s->seekg(-(sizeof(int_8)+1), ios::end);
288 GetTypeTag(ppstype);
289 if (ppstype != PPS_EOF)
290 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
291
292 int_8 pos;
293 GetRawI8(pos);
294 if (pos < 0) { // no tags
295 s->seekg(debut);
296 return;
297 }
298
299 char buffer[MAXTAGLEN+1];
300 s->seekg(pos);
301 while (true) {
302 GetTypeTag(ppstype);
303 if (ppstype == PPS_EOF) break;
304
305 if (ppstype != PPS_TAG)
306 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
307
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';
315
316 tags[buffer] = pos;
317 }
318 s->seekg(debut);
319}
320
321
322int
323PInPersist::NbTags()
324{
325 return tags.size();
326}
327
328bool
329PInPersist::GotoTag(string const& name)
330{
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);
336 objList.clear(); // $CHECK$ EA 171199
337 return(true);
338}
339
340bool
341PInPersist::GotoTagNum(int itag)
342{
343 if (itag<0 || itag >= (int)tags.size()) return false;
344 map<string, int_8>::iterator i = tags.begin();
345 for (int j=0; j<itag; j++) i++;
346 s->seekg((*i).second);
347 objList.clear(); // $CHECK$ EA 171199
348 return(true);
349}
350
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}
359
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
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
426void
427PInPersist::GetTypeTag(char& c)
428{
429 GetRawByte(c);
430 while (c == PPS_TAG_MARK) {
431 objList.clear();
432 GetRawByte(c);
433 }
434}
435
436
437void
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;
485 GetTypeTag(ppstype);
486 if (ppstype != PPS_SIMPLE + datasz)
487 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
488}
489
490void
491PInPersist::CheckArrayTag(short datasz, size_t sz)
492{
493 char ppstype;
494 GetTypeTag(ppstype);
495 size_t filesz;
496 if (sz <= 0x7fff) {
497 if (ppstype != PPS_SIMPLE_ARRAY + datasz)
498 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
499 int_2 ff;
500 GetRawI2(ff); filesz=ff;
501 } else if (sz <= 0x7fffffff) {
502 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
503 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
504 int_4 ff;
505 GetRawI4(ff); filesz=ff;
506 } else {
507 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
508 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
509 uint_8 ff;
510 GetRawU8(ff); filesz=ff;
511 }
512 if (filesz != sz)
513 throw FileFormatExc("PInPersist::CheckTag bad array size in ppersist file");
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
530PInPersist::GetR4 (r_4& result)
531{
532 CheckTag(4);
533 GetRawBytes(&result, sizeof(r_4));
534 if (bigEndian != IS_BIG_ENDIAN)
535 bswap4(&result);
536}
537
538
539void
540PInPersist::GetR4s (r_4* tab, size_t n)
541{
542 CheckArrayTag(4,n);
543 GetRawBytes(tab, n*sizeof(r_4));
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{
555 CheckTag(8);
556 GetRawBytes(&result, sizeof(r_8));
557 if (bigEndian != IS_BIG_ENDIAN)
558 bswap8(&result);
559}
560
561void
562PInPersist::GetR8s (r_8* tab, size_t n)
563{
564 CheckArrayTag(8,n);
565 GetRawBytes(tab, n*sizeof(r_8));
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{
577 CheckTag(2);
578 GetRawBytes(&result, sizeof(int_2));
579 if (bigEndian != IS_BIG_ENDIAN)
580 bswap2(&result);
581}
582
583void
584PInPersist::GetI2s (int_2* tab, size_t n)
585{
586 CheckArrayTag(2,n);
587 GetRawBytes(tab, n*sizeof(int_2));
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{
599 CheckTag(2);
600 GetRawBytes(&result, sizeof(uint_2));
601 if (bigEndian != IS_BIG_ENDIAN)
602 bswap2(&result);
603}
604
605void
606PInPersist::GetU2s (uint_2* tab, size_t n)
607{
608 CheckArrayTag(2,n);
609 GetRawBytes(tab, n*sizeof(uint_2));
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{
621 CheckTag(4);
622 GetRawBytes(&result, sizeof(int_4));
623 if (bigEndian != IS_BIG_ENDIAN)
624 bswap4(&result);
625}
626
627void
628PInPersist::GetI4s (int_4* tab, size_t n)
629{
630 CheckArrayTag(4,n);
631 GetRawBytes(tab, n*sizeof(int_4));
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{
643 CheckTag(4);
644 GetRawBytes(&result, sizeof(uint_4));
645 if (bigEndian != IS_BIG_ENDIAN)
646 bswap4(&result);
647}
648
649void
650PInPersist::GetU4s (uint_4* tab, size_t n)
651{
652 CheckArrayTag(4,n);
653 GetRawBytes(tab, n*sizeof(uint_4));
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{
666 CheckTag(8);
667 GetRawBytes(&result, sizeof(int_8));
668 if (bigEndian != IS_BIG_ENDIAN)
669 bswap8(&result);
670}
671
672void
673PInPersist::GetI8s (int_8* tab, size_t n)
674{
675 CheckArrayTag(8,n);
676 GetRawBytes(tab, n*sizeof(int_8));
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{
688 CheckTag(8);
689 GetRawBytes(&result, sizeof(uint_8));
690 if (bigEndian != IS_BIG_ENDIAN)
691 bswap8(&result);
692}
693
694void
695PInPersist::GetU8s (uint_8* tab, size_t n)
696{
697 CheckArrayTag(8,n);
698 GetRawBytes(tab, n*sizeof(uint_8));
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{
711 char ppstype;
712 GetTypeTag(ppstype);
713 if (ppstype != PPS_LINE)
714 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
715 s->getline(ptr, len, '\n');
716}
717
718void
719PInPersist::GetStr(string& str)
720{
721 char ppstype;
722 GetTypeTag(ppstype);
723 if (ppstype != PPS_STRING)
724 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
725 int_2 len;
726 GetRawI2(len);
727 char * buff = new char[len+1];
728 GetRawBytes(buff, len);
729 buff[len] = '\0';
730 str = buff;
731 delete[] buff;
732}
733
734PPersist*
735PInPersist::ReadObject()
736{
737 // Get tag
738 char ppstype;
739 GetTypeTag(ppstype);
740 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
741 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
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()) {
767 char msg[200];
768 sprintf(msg, "PInPersist::ReadObject invalid object id for reference: %d/%d",id,objList.size());
769 throw FileFormatExc(msg);
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
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
806 // Output stream creation
807 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
808
809 // Header
810 PutRawBytes("SOS-SOPHYA-PPersistFile V1 ",32);
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];
818 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
819 for(int i=l; i<32; i++) datestring[i] = ' ';
820 datestring[32] = '\0';
821 PutRawBytes(datestring, 32);
822}
823
824POutPersist::~POutPersist()
825{
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
849}
850
851
852void
853POutPersist::WriteTag(string const& name)
854{
855 if (name.length() > MAXTAGLEN)
856 throw ParmError("POutPersist::WriteTag tag name too long");
857
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
864 #ifdef STREAMPOS_IS_CLASS
865 tagPos = s->tellp().offset();
866 #else
867 tagPos = s->tellp();
868 #endif
869
870 tags[name] = tagPos;
871 PutRawByte(PPS_TAG_MARK); // This is a tag
872 objList.clear(); // $CHECK$ EA 171199
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)
894// void POutPersist::PutStr (string const&)
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
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
968POutPersist::PutByte(char c)
969{
970 PutRawByte(PPS_SIMPLE + 1);
971 PutRawBytes(&c, 1);
972}
973
974
975
976void
977POutPersist::PutBytes(void const* ptr, size_t bytes)
978{
979 PutArrayTag(1, bytes);
980 PutRawBytes(ptr, bytes);
981}
982
983void
984POutPersist::PutR4 (r_4 val)
985{
986 PutRawByte(PPS_SIMPLE + 4);
987
988 if (bigEndian != IS_BIG_ENDIAN)
989 bswap4(&val);
990
991 PutRawBytes(&val, sizeof(r_4));
992}
993
994void
995POutPersist::PutR4s (r_4 const* tab, size_t n)
996{
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 }
1008}
1009
1010void
1011POutPersist::PutR8 (r_8 val)
1012{
1013 PutRawByte(PPS_SIMPLE + 8);
1014
1015 if (bigEndian != IS_BIG_ENDIAN)
1016 bswap8(&val);
1017
1018 PutRawBytes(&val, sizeof(r_8));
1019}
1020
1021void
1022POutPersist::PutR8s (r_8 const* tab, size_t n)
1023{
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 }
1035}
1036
1037void
1038POutPersist::PutI2 (int_2 val)
1039{
1040 PutRawByte(PPS_SIMPLE + 2);
1041
1042 if (bigEndian != IS_BIG_ENDIAN)
1043 bswap2(&val);
1044
1045 PutRawBytes(&val, sizeof(int_2));
1046}
1047
1048void
1049POutPersist::PutI2s (int_2 const* tab, size_t n)
1050{
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 }
1062}
1063
1064void
1065POutPersist::PutU2 (uint_2 val)
1066{
1067 PutRawByte(PPS_SIMPLE + 2);
1068
1069 if (bigEndian != IS_BIG_ENDIAN)
1070 bswap2(&val);
1071
1072 PutRawBytes(&val, sizeof(uint_2));
1073}
1074
1075void
1076POutPersist::PutU2s (uint_2 const* tab, size_t n)
1077{
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 }
1089}
1090
1091void
1092POutPersist::PutI4 (int_4 val)
1093{
1094 PutRawByte(PPS_SIMPLE + 4);
1095
1096 if (bigEndian != IS_BIG_ENDIAN)
1097 bswap4(&val);
1098
1099 PutRawBytes(&val, sizeof(int_4));
1100}
1101
1102void
1103POutPersist::PutI4s (int_4 const* tab, size_t n)
1104{
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 }
1116}
1117
1118void
1119POutPersist::PutU4 (uint_4 val)
1120{
1121 PutRawByte(PPS_SIMPLE + 4);
1122
1123 if (bigEndian != IS_BIG_ENDIAN)
1124 bswap4(&val);
1125
1126 PutRawBytes(&val, sizeof(uint_4));
1127}
1128
1129void
1130POutPersist::PutU4s (uint_4 const* tab, size_t n)
1131{
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 }
1143}
1144
1145void
1146POutPersist::PutI8 (int_8 val)
1147{
1148 PutRawByte(PPS_SIMPLE + 8);
1149
1150 if (bigEndian != IS_BIG_ENDIAN)
1151 bswap8(&val);
1152
1153 PutRawBytes(&val, sizeof(int_8));
1154}
1155
1156void
1157POutPersist::PutI8s (int_8 const* tab, size_t n)
1158{
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 }
1170}
1171
1172void
1173POutPersist::PutU8 (uint_8 val)
1174{
1175 PutRawByte(PPS_SIMPLE + 8);
1176
1177 if (bigEndian != IS_BIG_ENDIAN)
1178 bswap8(&val);
1179
1180 PutRawBytes(&val, sizeof(uint_8));
1181}
1182
1183void
1184POutPersist::PutU8s (uint_8 const* tab, size_t n)
1185{
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 }
1197}
1198
1199void
1200POutPersist::PutStr(string const& str)
1201{
1202 PutRawByte(PPS_STRING);
1203 PutRawI2(str.length());
1204 PutRawBytes(str.c_str(), str.length());
1205}
1206
1207void
1208POutPersist::PutLine(char const* ptr, size_t len)
1209{
1210 PutRawByte(PPS_LINE);
1211
1212 if (len == 0) len = strlen(ptr);
1213 PutRawBytes(ptr, len);
1214 PutRawByte('\n');
1215}
1216
1217void
1218POutPersist::PutObject(PPersist const* obj)
1219{
1220 if (serializeNullAndRepeat(obj)) return;
1221
1222 PutRawByte(PPS_OBJECT);
1223 PutRawU8(getTypeId(typeid(*obj).name()));
1224 //PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
1225 assignObjectId(obj);
1226 obj->WriteSelf(*this);
1227}
1228
1229bool
1230POutPersist::serializeNullAndRepeat(PPersist const* x)
1231{
1232 if (x == NULL) {
1233 PutRawByte(PPS_NULL);
1234 return true;
1235 }
1236
1237 int_4 id = findObjectId(x);
1238 if (id >= 0) {
1239 PutRawByte(PPS_REFERENCE);
1240 PutRawI4(id);
1241 return true;
1242 }
1243
1244 return false;
1245}
1246
1247int_4
1248POutPersist::assignObjectId(PPersist const* x)
1249{
1250 int_4 id = objList.size();
1251 objList[x] = id;
1252 return id;
1253}
1254
1255int_4
1256POutPersist::findObjectId(PPersist const* x)
1257{
1258 ObjList::iterator i = objList.find(x);
1259 if (i == objList.end()) return -1;
1260 return (*i).second;
1261}
1262
1263
Note: See TracBrowser for help on using the repository browser.