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

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

PPersist version SOPHYA

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