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

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

Persist<NDataBlock> Reza 27/04/99

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