source: Sophya/trunk/Poubelle/DPC:FitsIOServer/SysTools/ppersist.cc@ 4080

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

no message

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