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

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

Corr. bug et ajout Methodes PInPersist::GetTagName - Reza 16/11/99

File size: 25.4 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 >= (int)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
337string
338PInPersist::GetTagName(int itag)
339{
340 if (itag<0 || itag >= (int)tags.size()) return "";
341 map<string, int_8>::iterator i = tags.begin();
342 for (int j=0; j<itag; j++) i++;
343 return((*i).first);
344}
345
346static vector<string> * ret_tag_names = NULL;
347vector<string> const &
348PInPersist::GetTagNames()
349{
350if (ret_tag_names) delete ret_tag_names;
351ret_tag_names = new vector<string> ;
352map<string, int_8>::iterator i;
353for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
354return(*ret_tag_names);
355}
356
357//++
358// void PInPersist::GetByte(char& c)
359// void PInPersist::GetBytes(void* ptr, size_t bytes)
360// void PInPersist::GetR4 (r_4& result)
361// void PInPersist::GetR4s (r_4* tab, size_t n)
362// void PInPersist::GetR8 (r_8& result)
363// void PInPersist::GetR8s (r_8* tab, size_t n)
364// void PInPersist::GetI2 (int_2& result)
365// void PInPersist::GetI2s (int_2* tab, size_t n)
366// void PInPersist::GetU2 (uint_2& result)
367// void PInPersist::GetU2s (uint_2* tab, size_t n)
368// void PInPersist::GetI4 (int_4& result)
369// void PInPersist::GetI4s (int_4* tab, size_t n)
370// void PInPersist::GetU4 (uint_4& result)
371// void PInPersist::GetU4s (uint_4* tab, size_t n)
372// void PInPersist::GetI8 (int_8& result)
373// void PInPersist::GetI8s (int_8* tab, size_t n)
374// void PInPersist::GetU8 (uint_8& result)
375// void PInPersist::GetU8s (uint_8* tab, size_t n)
376// Lecture de données portables depuis le fichier PPersist. Pour chaque type
377// de données, on peut lire une valeur, ou un tableau de valeurs.
378// void PInPersist::GetLine(char* ptr, size_t len)
379// Lecture d'une ligne de texte depuis le fichier PPersist.
380//--
381
382
383static inline void bswap8(void* p)
384{
385 uint_8 tmp = *(uint_8*)p;
386 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
387 ((tmp >> (5*8)) & 0x0000FF00) |
388 ((tmp >> (3*8)) & 0x00FF0000) |
389 ((tmp >> (1*8)) & 0xFF000000) |
390 ((tmp & 0xFF000000) << (1*8)) |
391 ((tmp & 0x00FF0000) << (3*8)) |
392 ((tmp & 0x0000FF00) << (5*8)) |
393 ((tmp & 0x000000FF) << (7*8));
394}
395
396static inline void bswap4(void* p)
397{
398 uint_4 tmp = *(uint_4*)p;
399 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
400 ((tmp >> 8) & 0x0000FF00) |
401 ((tmp & 0x0000FF00) << 8) |
402 ((tmp & 0x000000FF) << 24);
403}
404
405static inline void bswap2(void* p)
406{
407 uint_2 tmp = *(uint_2*)p;
408 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
409 ((tmp & 0x00FF) << 8);
410}
411
412
413void
414PInPersist::GetRawByte(char& c)
415{
416 GetRawBytes(&c, 1);
417}
418
419void
420PInPersist::GetRawBytes(void* ptr, size_t bytes)
421{
422 s->read((char*)ptr, bytes);
423}
424
425void
426PInPersist::GetRawI2 (int_2& result)
427{
428 GetRawBytes(&result, sizeof(int_2));
429 if (bigEndian != IS_BIG_ENDIAN)
430 bswap2(&result);
431}
432
433void
434PInPersist::GetRawI4 (int_4& result)
435{
436 GetRawBytes(&result, sizeof(int_4));
437 if (bigEndian != IS_BIG_ENDIAN)
438 bswap4(&result);
439}
440
441void
442PInPersist::GetRawI8 (int_8& result)
443{
444 GetRawBytes(&result, sizeof(int_8));
445 if (bigEndian != IS_BIG_ENDIAN)
446 bswap8(&result);
447}
448
449void
450PInPersist::GetRawU8 (uint_8& result)
451{
452 GetRawBytes(&result, sizeof(uint_8));
453 if (bigEndian != IS_BIG_ENDIAN)
454 bswap8(&result);
455}
456
457void
458PInPersist::CheckTag(short datasz)
459{
460 char ppstype;
461 GetRawByte(ppstype);
462 if (ppstype != PPS_SIMPLE + datasz)
463 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
464}
465
466void
467PInPersist::CheckArrayTag(short datasz, size_t sz)
468{
469 char ppstype;
470 GetRawByte(ppstype);
471 size_t filesz;
472 if (sz <= 0x7fff) {
473 if (ppstype != PPS_SIMPLE_ARRAY + datasz)
474 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
475 int_2 ff;
476 GetRawI2(ff); filesz=ff;
477 } else if (sz <= 0x7fffffff) {
478 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
479 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
480 int_4 ff;
481 GetRawI4(ff); filesz=ff;
482 } else {
483 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
484 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
485 uint_8 ff;
486 GetRawU8(ff); filesz=ff;
487 }
488 if (filesz != sz)
489 throw FileFormatExc("PInPersist::CheckTag bad array size in ppersist file");
490}
491
492void
493PInPersist::GetByte(char& c)
494{
495 CheckTag(1);
496 GetRawBytes(&c, 1);
497}
498
499void
500PInPersist::GetBytes(void* ptr, size_t bytes)
501{
502 CheckArrayTag(1, bytes);
503 GetRawBytes(ptr, bytes);
504}
505void
506PInPersist::GetR4 (r_4& result)
507{
508 CheckTag(4);
509 GetRawBytes(&result, sizeof(r_4));
510 if (bigEndian != IS_BIG_ENDIAN)
511 bswap4(&result);
512}
513
514
515void
516PInPersist::GetR4s (r_4* tab, size_t n)
517{
518 CheckArrayTag(4,n);
519 GetRawBytes(tab, n*sizeof(r_4));
520 if (bigEndian == IS_BIG_ENDIAN) return;
521
522 for (unsigned int i=0; i<n; i++)
523 bswap4(tab+i);
524
525 return;
526}
527
528void
529PInPersist::GetR8 (r_8& result)
530{
531 CheckTag(8);
532 GetRawBytes(&result, sizeof(r_8));
533 if (bigEndian != IS_BIG_ENDIAN)
534 bswap8(&result);
535}
536
537void
538PInPersist::GetR8s (r_8* tab, size_t n)
539{
540 CheckArrayTag(8,n);
541 GetRawBytes(tab, n*sizeof(r_8));
542 if (bigEndian == IS_BIG_ENDIAN) return;
543
544 for (unsigned int i=0; i<n; i++)
545 bswap8(tab+i);
546
547 return;
548}
549
550void
551PInPersist::GetI2 (int_2& result)
552{
553 CheckTag(2);
554 GetRawBytes(&result, sizeof(int_2));
555 if (bigEndian != IS_BIG_ENDIAN)
556 bswap2(&result);
557}
558
559void
560PInPersist::GetI2s (int_2* tab, size_t n)
561{
562 CheckArrayTag(2,n);
563 GetRawBytes(tab, n*sizeof(int_2));
564 if (bigEndian == IS_BIG_ENDIAN) return;
565
566 for (unsigned int i=0; i<n; i++)
567 bswap2(tab+i);
568
569 return;
570}
571
572void
573PInPersist::GetU2 (uint_2& result)
574{
575 CheckTag(2);
576 GetRawBytes(&result, sizeof(uint_2));
577 if (bigEndian != IS_BIG_ENDIAN)
578 bswap2(&result);
579}
580
581void
582PInPersist::GetU2s (uint_2* tab, size_t n)
583{
584 CheckArrayTag(2,n);
585 GetRawBytes(tab, n*sizeof(uint_2));
586 if (bigEndian == IS_BIG_ENDIAN) return;
587
588 for (unsigned int i=0; i<n; i++)
589 bswap2(tab+i);
590
591 return;
592}
593
594void
595PInPersist::GetI4 (int_4& result)
596{
597 CheckTag(4);
598 GetRawBytes(&result, sizeof(int_4));
599 if (bigEndian != IS_BIG_ENDIAN)
600 bswap4(&result);
601}
602
603void
604PInPersist::GetI4s (int_4* tab, size_t n)
605{
606 CheckArrayTag(4,n);
607 GetRawBytes(tab, n*sizeof(int_4));
608 if (bigEndian == IS_BIG_ENDIAN) return;
609
610 for (unsigned int i=0; i<n; i++)
611 bswap4(tab+i);
612
613 return;
614}
615
616void
617PInPersist::GetU4 (uint_4& result)
618{
619 CheckTag(4);
620 GetRawBytes(&result, sizeof(uint_4));
621 if (bigEndian != IS_BIG_ENDIAN)
622 bswap4(&result);
623}
624
625void
626PInPersist::GetU4s (uint_4* tab, size_t n)
627{
628 CheckArrayTag(4,n);
629 GetRawBytes(tab, n*sizeof(uint_4));
630 if (bigEndian == IS_BIG_ENDIAN) return;
631
632 for (unsigned int i=0; i<n; i++)
633 bswap4(tab+i);
634
635 return;
636}
637
638
639void
640PInPersist::GetI8 (int_8& result)
641{
642 CheckTag(8);
643 GetRawBytes(&result, sizeof(int_8));
644 if (bigEndian != IS_BIG_ENDIAN)
645 bswap8(&result);
646}
647
648void
649PInPersist::GetI8s (int_8* tab, size_t n)
650{
651 CheckArrayTag(8,n);
652 GetRawBytes(tab, n*sizeof(int_8));
653 if (bigEndian == IS_BIG_ENDIAN) return;
654
655 for (unsigned int i=0; i<n; i++)
656 bswap8(tab+i);
657
658 return;
659}
660
661void
662PInPersist::GetU8 (uint_8& result)
663{
664 CheckTag(8);
665 GetRawBytes(&result, sizeof(uint_8));
666 if (bigEndian != IS_BIG_ENDIAN)
667 bswap8(&result);
668}
669
670void
671PInPersist::GetU8s (uint_8* tab, size_t n)
672{
673 CheckArrayTag(8,n);
674 GetRawBytes(tab, n*sizeof(uint_8));
675 if (bigEndian == IS_BIG_ENDIAN) return;
676
677 for (unsigned int i=0; i<n; i++)
678 bswap8(tab+i);
679
680 return;
681}
682
683
684void
685PInPersist::GetLine(char* ptr, size_t len)
686{
687 char ppstype;
688 GetRawByte(ppstype);
689 if (ppstype != PPS_LINE)
690 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
691 s->getline(ptr, len, '\n');
692}
693
694void
695PInPersist::GetStr(string& str)
696{
697 char ppstype;
698 GetRawByte(ppstype);
699 if (ppstype != PPS_STRING)
700 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
701 int_2 len;
702 GetRawI2(len);
703 char * buff = new char[len+1];
704 GetRawBytes(buff, len);
705 buff[len] = '\0';
706 str = buff;
707 delete[] buff;
708}
709
710PPersist*
711PInPersist::ReadObject()
712{
713 // Get tag
714 char ppstype;
715 GetRawByte(ppstype);
716 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
717 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
718 }
719
720 if (ppstype == PPS_NULL) {
721 return NULL;
722 } else if (ppstype == PPS_OBJECT) {
723 // Get class id
724 uint_8 classId;
725 GetRawU8(classId);
726
727 // Get factory method
728 ClassCreatorFunc f = FindCreatorFunc(classId);
729 if (!f) {
730 throw NotFoundExc("PInPersist::ReadObject class not registered");
731 }
732
733 // Create object
734 PPersist* object = f();
735 object->ReadSelf(*this);
736 assignObjectId(object);
737 return object;
738 } else {
739 // Get object id
740 int_4 id;
741 GetRawI4(id);
742 if (id <0 || id>=objList.size()) {
743 throw FileFormatExc("PInPersist::ReadObject invalid object id for reference");
744 }
745 return objList[id];
746 }
747}
748
749int_4
750PInPersist::assignObjectId(PPersist* x)
751{
752 objList.push_back(x);
753 return objList.size()-1;
754}
755
756//++
757// Class POutPersist
758// Lib Outils++
759// include ppersist.h
760//
761// Fichier d'objets persistants, en écriture.
762//--
763
764
765//++
766// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
767//
768// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
769// sur machines petit-boutiennes, et gros-boutien sur machines
770// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
771// ou PPersist::PPS_BIG_ENDIAN.
772//--
773POutPersist::POutPersist(string const& flnm, int endianness)
774{
775 if (endianness == -1)
776 bigEndian = IS_BIG_ENDIAN;
777 else
778 bigEndian = endianness;
779
780 // Output stream creation
781 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
782
783 // Header
784 PutRawBytes("SOS-SOPHYA-PPersistFile V1 ",32);
785 PutRawBytes(bigEndian
786 ? "BIG-ENDIAN "
787 : "LITTLE-ENDIAN ",32);
788
789// ---- GMT creation date of the file
790 time_t tm = time(NULL);
791 char datestring[33];
792 int l=strftime(datestring,32,"%d/%m/%Y %T GMT",gmtime(&tm));
793 for(int i=l; i<32; i++) datestring[i] = ' ';
794 datestring[32] = '\0';
795 PutRawBytes(datestring, 32);
796}
797
798POutPersist::~POutPersist()
799{
800 if (tags.size() == 0) {
801 PutRawByte(PPS_EOF);
802 PutRawI8(-1);
803 } else {
804 int_8 tagPos;
805#ifdef STREAMPOS_IS_CLASS
806 tagPos = s->tellp().offset();
807#else
808 tagPos = s->tellp();
809#endif
810 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
811 string name = (*i).first;
812 int_8 pos = (*i).second;
813 PutRawByte(PPS_TAG); // This is a tag
814 PutRawI8(pos); // position of previous tag
815 PutRawI4(name.length()); // length of the name
816 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
817 }
818 PutRawByte(PPS_EOF);
819 PutRawI8(tagPos);
820 }
821
822 delete s; // Close the stream
823}
824
825
826void
827POutPersist::WriteTag(string const& name)
828{
829 if (name.length() > MAXTAGLEN)
830 throw ParmError("POutPersist::WriteTag tag name too long");
831
832 if (tags.find(name) != tags.end())
833 throw DuplicateIdExc("POutPersist::WriteTag duplicate tag name");
834
835 // Get current file position
836 int_8 tagPos;
837
838 #ifdef STREAMPOS_IS_CLASS
839 tagPos = s->tellp().offset();
840 #else
841 tagPos = s->tellp();
842 #endif
843
844 tags[name] = tagPos;
845}
846
847//++
848// void POutPersist::PutByte(char& c)
849// void POutPersist::PutBytes(void const* ptr, size_t bytes)
850// void POutPersist::PutR4 (r_4 result)
851// void POutPersist::PutR4s (r_4 const* tab, size_t n)
852// void POutPersist::PutR8 (r_8 result)
853// void POutPersist::PutR8s (r_8 const* tab, size_t n)
854// void POutPersist::PutI2 (int_2 result)
855// void POutPersist::PutI2s (int_2 const* tab, size_t n)
856// void POutPersist::PutU2 (uint_2 result)
857// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
858// void POutPersist::PutI4 (int_4 result)
859// void POutPersist::PutI4s (int_4 const* tab, size_t n)
860// void POutPersist::PutU4 (uint_4 result)
861// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
862// void POutPersist::PutI8 (int_8 result)
863// void POutPersist::PutI8s (int_8 const* tab, size_t n)
864// void POutPersist::PutU8 (uint_8 result)
865// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
866// void POutPersist::PutStr (string const&)
867// Ecriture de données portables.. Pour chaque type
868// de données, on peut écrire une valeur, ou un tableau de valeurs.
869// void POutPersist::PutLine(char const* ptr, size_t len)
870// Ecriture d'une ligne de texte dans le fichier PPersist.
871//--
872
873
874
875
876void
877POutPersist::PutRawBytes(void const* ptr, size_t bytes)
878{
879 s->write((char const*)ptr, bytes);
880}
881
882void
883POutPersist::PutRawByte(char c)
884{
885 PutRawBytes(&c, 1);
886}
887
888void
889POutPersist::PutRawI2 (int_2 val)
890{
891 if (bigEndian != IS_BIG_ENDIAN)
892 bswap2(&val);
893
894 PutRawBytes(&val, sizeof(int_2));
895}
896
897void
898POutPersist::PutRawI4 (int_4 val)
899{
900 if (bigEndian != IS_BIG_ENDIAN)
901 bswap4(&val);
902
903 PutRawBytes(&val, sizeof(int_4));
904}
905
906void
907POutPersist::PutRawI8 (int_8 val)
908{
909 if (bigEndian != IS_BIG_ENDIAN)
910 bswap8(&val);
911
912 PutRawBytes(&val, sizeof(int_8));
913}
914
915void
916POutPersist::PutRawU8 (uint_8 val)
917{
918 if (bigEndian != IS_BIG_ENDIAN)
919 bswap8(&val);
920
921 PutRawBytes(&val, sizeof(uint_8));
922}
923
924void
925POutPersist::PutArrayTag(short datasz, size_t sz)
926{
927 if (sz <= 0x7fff) {
928 PutRawByte(PPS_SIMPLE_ARRAY + datasz);
929 PutRawI2(sz);
930 } else if (sz <= 0x7fffffff) {
931 PutRawByte(PPS_SIMPLE_ARRAY4 + datasz);
932 PutRawI4(sz);
933 } else {
934 PutRawByte(PPS_SIMPLE_ARRAY8 + datasz);
935 PutRawU8(sz);
936 }
937}
938
939void
940POutPersist::PutByte(char c)
941{
942 PutRawByte(PPS_SIMPLE + 1);
943 PutRawBytes(&c, 1);
944}
945
946
947
948void
949POutPersist::PutBytes(void const* ptr, size_t bytes)
950{
951 PutArrayTag(1, bytes);
952 PutRawBytes(ptr, bytes);
953}
954
955void
956POutPersist::PutR4 (r_4 val)
957{
958 PutRawByte(PPS_SIMPLE + 4);
959
960 if (bigEndian != IS_BIG_ENDIAN)
961 bswap4(&val);
962
963 PutRawBytes(&val, sizeof(r_4));
964}
965
966void
967POutPersist::PutR4s (r_4 const* tab, size_t n)
968{
969 PutArrayTag(4, n);
970
971 if (bigEndian == IS_BIG_ENDIAN) {
972 PutRawBytes(tab, n*sizeof(r_4));
973 } else {
974 for (unsigned int i=0; i<n; i++) {
975 r_4 val = tab[i];
976 bswap4(&val);
977 PutRawBytes(&val, sizeof(r_4));
978 }
979 }
980}
981
982void
983POutPersist::PutR8 (r_8 val)
984{
985 PutRawByte(PPS_SIMPLE + 8);
986
987 if (bigEndian != IS_BIG_ENDIAN)
988 bswap8(&val);
989
990 PutRawBytes(&val, sizeof(r_8));
991}
992
993void
994POutPersist::PutR8s (r_8 const* tab, size_t n)
995{
996 PutArrayTag(8, n);
997
998 if (bigEndian == IS_BIG_ENDIAN) {
999 PutRawBytes(tab, n*sizeof(r_8));
1000 } else {
1001 for (unsigned int i=0; i<n; i++) {
1002 r_8 val = tab[i];
1003 bswap8(&val);
1004 PutRawBytes(&val, sizeof(r_8));
1005 }
1006 }
1007}
1008
1009void
1010POutPersist::PutI2 (int_2 val)
1011{
1012 PutRawByte(PPS_SIMPLE + 2);
1013
1014 if (bigEndian != IS_BIG_ENDIAN)
1015 bswap2(&val);
1016
1017 PutRawBytes(&val, sizeof(int_2));
1018}
1019
1020void
1021POutPersist::PutI2s (int_2 const* tab, size_t n)
1022{
1023 PutArrayTag(2, n);
1024
1025 if (bigEndian == IS_BIG_ENDIAN) {
1026 PutRawBytes(tab, n*sizeof(int_2));
1027 } else {
1028 for (unsigned int i=0; i<n; i++) {
1029 int_2 val = tab[i];
1030 bswap2(&val);
1031 PutRawBytes(&val, sizeof(int_2));
1032 }
1033 }
1034}
1035
1036void
1037POutPersist::PutU2 (uint_2 val)
1038{
1039 PutRawByte(PPS_SIMPLE + 2);
1040
1041 if (bigEndian != IS_BIG_ENDIAN)
1042 bswap2(&val);
1043
1044 PutRawBytes(&val, sizeof(uint_2));
1045}
1046
1047void
1048POutPersist::PutU2s (uint_2 const* tab, size_t n)
1049{
1050 PutArrayTag(2, n);
1051
1052 if (bigEndian == IS_BIG_ENDIAN) {
1053 PutRawBytes(tab, n*sizeof(uint_2));
1054 } else {
1055 for (unsigned int i=0; i<n; i++) {
1056 uint_2 val = tab[i];
1057 bswap2(&val);
1058 PutRawBytes(&val, sizeof(uint_2));
1059 }
1060 }
1061}
1062
1063void
1064POutPersist::PutI4 (int_4 val)
1065{
1066 PutRawByte(PPS_SIMPLE + 4);
1067
1068 if (bigEndian != IS_BIG_ENDIAN)
1069 bswap4(&val);
1070
1071 PutRawBytes(&val, sizeof(int_4));
1072}
1073
1074void
1075POutPersist::PutI4s (int_4 const* tab, size_t n)
1076{
1077 PutArrayTag(4, n);
1078
1079 if (bigEndian == IS_BIG_ENDIAN) {
1080 PutRawBytes(tab, n*sizeof(int_4));
1081 } else {
1082 for (unsigned int i=0; i<n; i++) {
1083 int_4 val = tab[i];
1084 bswap4(&val);
1085 PutRawBytes(&val, sizeof(int_4));
1086 }
1087 }
1088}
1089
1090void
1091POutPersist::PutU4 (uint_4 val)
1092{
1093 PutRawByte(PPS_SIMPLE + 4);
1094
1095 if (bigEndian != IS_BIG_ENDIAN)
1096 bswap4(&val);
1097
1098 PutRawBytes(&val, sizeof(uint_4));
1099}
1100
1101void
1102POutPersist::PutU4s (uint_4 const* tab, size_t n)
1103{
1104 PutArrayTag(4, n);
1105
1106 if (bigEndian == IS_BIG_ENDIAN) {
1107 PutRawBytes(tab, n*sizeof(uint_4));
1108 } else {
1109 for (unsigned int i=0; i<n; i++) {
1110 uint_4 val = tab[i];
1111 bswap4(&val);
1112 PutRawBytes(&val, sizeof(uint_4));
1113 }
1114 }
1115}
1116
1117void
1118POutPersist::PutI8 (int_8 val)
1119{
1120 PutRawByte(PPS_SIMPLE + 8);
1121
1122 if (bigEndian != IS_BIG_ENDIAN)
1123 bswap8(&val);
1124
1125 PutRawBytes(&val, sizeof(int_8));
1126}
1127
1128void
1129POutPersist::PutI8s (int_8 const* tab, size_t n)
1130{
1131 PutArrayTag(8, n);
1132
1133 if (bigEndian == IS_BIG_ENDIAN) {
1134 PutRawBytes(tab, n*sizeof(int_8));
1135 } else {
1136 for (unsigned int i=0; i<n; i++) {
1137 int_8 val = tab[i];
1138 bswap8(&val);
1139 PutRawBytes(&val, sizeof(int_8));
1140 }
1141 }
1142}
1143
1144void
1145POutPersist::PutU8 (uint_8 val)
1146{
1147 PutRawByte(PPS_SIMPLE + 8);
1148
1149 if (bigEndian != IS_BIG_ENDIAN)
1150 bswap8(&val);
1151
1152 PutRawBytes(&val, sizeof(uint_8));
1153}
1154
1155void
1156POutPersist::PutU8s (uint_8 const* tab, size_t n)
1157{
1158 PutArrayTag(8, n);
1159
1160 if (bigEndian == IS_BIG_ENDIAN) {
1161 PutRawBytes(tab, n*sizeof(uint_8));
1162 } else {
1163 for (unsigned int i=0; i<n; i++) {
1164 uint_8 val = tab[i];
1165 bswap8(&val);
1166 PutRawBytes(&val, sizeof(uint_8));
1167 }
1168 }
1169}
1170
1171void
1172POutPersist::PutStr(string const& str)
1173{
1174 PutRawByte(PPS_STRING);
1175 PutRawI2(str.length());
1176 PutRawBytes(str.c_str(), str.length());
1177}
1178
1179void
1180POutPersist::PutLine(char const* ptr, size_t len)
1181{
1182 PutRawByte(PPS_LINE);
1183
1184 if (len == 0) len = strlen(ptr);
1185 PutRawBytes(ptr, len);
1186 PutRawByte('\n');
1187}
1188
1189void
1190POutPersist::PutObject(PPersist const* obj)
1191{
1192 if (serializeNullAndRepeat(obj)) return;
1193
1194 PutRawByte(PPS_OBJECT);
1195 PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
1196 assignObjectId(obj);
1197 obj->WriteSelf(*this);
1198}
1199
1200bool
1201POutPersist::serializeNullAndRepeat(PPersist const* x)
1202{
1203 if (x == NULL) {
1204 PutRawByte(PPS_NULL);
1205 return true;
1206 }
1207
1208 int_4 id = findObjectId(x);
1209 if (id >= 0) {
1210 PutRawByte(PPS_REFERENCE);
1211 PutRawI4(id);
1212 return true;
1213 }
1214
1215 return false;
1216}
1217
1218int_4
1219POutPersist::assignObjectId(PPersist const* x)
1220{
1221 int_4 id = objList.size();
1222 objList[x] = id;
1223 return id;
1224}
1225
1226int_4
1227POutPersist::findObjectId(PPersist const* x)
1228{
1229 ObjList::iterator i = objList.find(x);
1230 if (i == objList.end()) return -1;
1231 return (*i).second;
1232}
1233
1234
Note: See TracBrowser for help on using the repository browser.