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

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

Persist<NDataBlock> Reza 27/04/99

File size: 24.9 KB
RevLine 
[241]1#include "machdefs.h"
[251]2#include <stdio.h>
3#include <sys/types.h>
4#include <time.h>
[241]5#include "pexceptions.h"
[219]6#include "peidainit.h"
7#include "ppersist.h"
8#include <fstream.h>
[241]9#include <typeinfo>
[219]10
11
12#ifdef __mac__
13#include "unixmac.h"
14#include <SIOUX.h>
15#endif
16
[241]17using namespace PlanckDPC;
[219]18
[241]19#define MAXTAGLEN 255
20
[219]21//++
[241]22// Class PIOPersist
[219]23// Lib Outils++
24// include ppersist.h
25//
[241]26// Root class for persistant files. Handles the registration of
27// persistant classes
[219]28//--
29
30//++
[241]31// Links See
[219]32// PPersist
[241]33// PInPersist
34// POutPersist
[219]35//--
36
37
[241]38MD5_CTX PIOPersist::ctx;
[269]39PIOPersist::ClassList * PIOPersist::classList = NULL; // $CHECK$ Reza 26/04/99
[241]40
[269]41//++
42void
43PIOPersist::Initialize()
44// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
45//--
46{
47classList = new PIOPersist::ClassList;
48}
[241]49
[219]50//++
51void
[241]52PIOPersist::RegisterClass(uint_8 classId, ClassCreatorFunc f)
[219]53//
[241]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.
[219]58//
59//--
60{
[269]61 if (classList->size() && (classList->find(classId) != classList->end())) {
[219]62 cerr << "RegisterClass : Error, " << hex << classId << dec
63 << " already registered." << endl;
[241]64 throw(DuplicateIdExc("PIOPersist::RegisterClass"));
[219]65 }
66
[269]67 (*classList)[classId] = f;
[219]68}
69
70
[241]71PIOPersist::ClassCreatorFunc
72PIOPersist::FindCreatorFunc(uint_8 classId)
[219]73{
[269]74 ClassList::iterator i = classList->find(classId);
75 if (i == classList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc"));
[241]76 return (*i).second;
[219]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//++
[241]104// Links See
[219]105// PInPersist
106// POutPersist
[241]107// PIOPersist
[219]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{
[241]141 s.PutObject(this);
[219]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
[241]151// objet, utiliser PInPersist::ReadObject.
152// Il faut qu'on soit un objet ecrit
[219]153//--
154{
[241]155 // We should be the exact type
156 // Check tag value
157 char ppstype;
158 s.GetRawByte(ppstype);
159 if (ppstype != PInPersist::PPS_OBJECT) {
[256]160 throw FileFormatExc("PPersist::Read : not an object in flow");
[241]161 }
162
163 // Check class id
164 uint_8 classId;
165 s.GetRawU8(classId);
166 if (classId != PIOPersist::Hash(typeid(*this).name())) {
[256]167 throw FileFormatExc("PPersist::Read : not the same object type");
[241]168 }
[219]169
[241]170 ReadSelf(s);
[219]171}
172
173//++
[241]174void
175PPersist::Write(POutPersist& s, string const& tag) const
[219]176//
[241]177// Ecrit l'objet dans le fichier PPersist avec un tag
[219]178//--
179{
[241]180 s.WriteTag(tag);
181 s.PutObject(this);
[219]182}
183
184//++
185void
[241]186PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]187//
188// Lit l'objet à la position du tag numéro "tagid".
189//--
190{
[241]191 if (!s.GotoTag(tag))
192 throw NotFoundExc("PPersist::ReadAtTag tag not found");
193 Read(s);
[219]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{
[241]224 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
225
226 // Read and check header
227
[219]228 char rbuf[36];
[241]229 GetRawBytes(rbuf, 32);
230 if (strncmp(rbuf,"PlanckDPC-PPersistFile", 22) != 0) {
231 throw FileFormatExc("PInPersist::PInPersist bad header");
[219]232 }
[241]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();
[219]253}
254
255
256
257PInPersist::~PInPersist()
258{
259 delete s;
260}
261
262
263void
264PInPersist::Scan()
265{
[241]266 // On cherche la liste des tags, a la fin du fichier
[219]267
[241]268 char ppstype;
269 size_t debut;
270#ifdef STREAMPOS_IS_CLASS
[219]271 debut = s->tellg().offset();
[241]272#else
[219]273 debut = s->tellg();
[241]274#endif
[219]275
[241]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");
[219]281
[241]282 int_8 pos;
283 GetRawI8(pos);
284 if (pos < 0) { // no tags
285 s->seekg(debut);
286 return;
287 }
[219]288
[241]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");
[219]297
[241]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';
[219]305
[241]306 tags[buffer] = pos;
[219]307 }
[241]308 s->seekg(debut);
[219]309}
310
311
[256]312int
313PInPersist::NbTags()
314{
315 return tags.size();
316}
317
[219]318bool
[241]319PInPersist::GotoTag(string const& name)
[219]320{
[241]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);
[219]326 return(true);
327}
328
[256]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
[219]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
[241]395
[219]396void
[241]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)
[256]446 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]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)
[256]457 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]458 int_2 ff;
459 GetRawI2(ff); filesz=ff;
460 } else if (sz <= 0x7fffffff) {
461 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz)
[256]462 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]463 int_4 ff;
464 GetRawI4(ff); filesz=ff;
465 } else {
466 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz)
[256]467 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]468 uint_8 ff;
469 GetRawU8(ff); filesz=ff;
470 }
471 if (filesz != sz)
[256]472 throw FileFormatExc("PInPersist::CheckTag bad array size in ppersist file");
[241]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
[219]489PInPersist::GetR4 (r_4& result)
490{
[241]491 CheckTag(4);
492 GetRawBytes(&result, sizeof(r_4));
[219]493 if (bigEndian != IS_BIG_ENDIAN)
494 bswap4(&result);
495}
496
497
498void
499PInPersist::GetR4s (r_4* tab, size_t n)
500{
[241]501 CheckArrayTag(4,n);
502 GetRawBytes(tab, n*sizeof(r_4));
[219]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{
[241]514 CheckTag(8);
515 GetRawBytes(&result, sizeof(r_8));
[219]516 if (bigEndian != IS_BIG_ENDIAN)
517 bswap8(&result);
518}
519
520void
521PInPersist::GetR8s (r_8* tab, size_t n)
522{
[241]523 CheckArrayTag(8,n);
524 GetRawBytes(tab, n*sizeof(r_8));
[219]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{
[241]536 CheckTag(2);
537 GetRawBytes(&result, sizeof(int_2));
[219]538 if (bigEndian != IS_BIG_ENDIAN)
539 bswap2(&result);
540}
541
542void
543PInPersist::GetI2s (int_2* tab, size_t n)
544{
[241]545 CheckArrayTag(2,n);
546 GetRawBytes(tab, n*sizeof(int_2));
[219]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{
[241]558 CheckTag(2);
559 GetRawBytes(&result, sizeof(uint_2));
[219]560 if (bigEndian != IS_BIG_ENDIAN)
561 bswap2(&result);
562}
563
564void
565PInPersist::GetU2s (uint_2* tab, size_t n)
566{
[241]567 CheckArrayTag(2,n);
568 GetRawBytes(tab, n*sizeof(uint_2));
[219]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{
[241]580 CheckTag(4);
581 GetRawBytes(&result, sizeof(int_4));
[219]582 if (bigEndian != IS_BIG_ENDIAN)
583 bswap4(&result);
584}
585
586void
587PInPersist::GetI4s (int_4* tab, size_t n)
588{
[241]589 CheckArrayTag(4,n);
590 GetRawBytes(tab, n*sizeof(int_4));
[219]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{
[241]602 CheckTag(4);
603 GetRawBytes(&result, sizeof(uint_4));
[219]604 if (bigEndian != IS_BIG_ENDIAN)
605 bswap4(&result);
606}
607
608void
609PInPersist::GetU4s (uint_4* tab, size_t n)
610{
[241]611 CheckArrayTag(4,n);
612 GetRawBytes(tab, n*sizeof(uint_4));
[219]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{
[241]625 CheckTag(8);
626 GetRawBytes(&result, sizeof(int_8));
[219]627 if (bigEndian != IS_BIG_ENDIAN)
628 bswap8(&result);
629}
630
631void
632PInPersist::GetI8s (int_8* tab, size_t n)
633{
[241]634 CheckArrayTag(8,n);
635 GetRawBytes(tab, n*sizeof(int_8));
[219]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{
[241]647 CheckTag(8);
648 GetRawBytes(&result, sizeof(uint_8));
[219]649 if (bigEndian != IS_BIG_ENDIAN)
650 bswap8(&result);
651}
652
653void
654PInPersist::GetU8s (uint_8* tab, size_t n)
655{
[241]656 CheckArrayTag(8,n);
657 GetRawBytes(tab, n*sizeof(uint_8));
[219]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{
[241]670 char ppstype;
671 GetRawByte(ppstype);
672 if (ppstype != PPS_LINE)
[256]673 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
[241]674 s->getline(ptr, len, '\n');
[219]675}
676
[241]677void
678PInPersist::GetStr(string& str)
679{
680 char ppstype;
681 GetRawByte(ppstype);
682 if (ppstype != PPS_STRING)
[256]683 throw FileFormatExc("PInPersist::GetLine bad type in ppersist file");
[241]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}
[219]692
[241]693PPersist*
694PInPersist::ReadObject()
695{
696 // Get tag
697 char ppstype;
698 GetRawByte(ppstype);
699 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]700 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]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
[219]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
[241]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);
[219]779}
780
781POutPersist::~POutPersist()
782{
[241]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
[219]806}
807
808
[241]809void
810POutPersist::WriteTag(string const& name)
[219]811{
[241]812 if (name.length() > MAXTAGLEN)
813 throw ParmError("POutPersist::WriteTag tag name too long");
[219]814
[241]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
[219]821 #ifdef STREAMPOS_IS_CLASS
[241]822 tagPos = s->tellp().offset();
[219]823 #else
[241]824 tagPos = s->tellp();
[219]825 #endif
[241]826
827 tags[name] = tagPos;
[219]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)
[241]849// void POutPersist::PutStr (string const&)
[219]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
[241]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
[219]923POutPersist::PutByte(char c)
924{
[241]925 PutRawByte(PPS_SIMPLE + 1);
926 PutRawBytes(&c, 1);
[219]927}
928
[241]929
930
[219]931void
932POutPersist::PutBytes(void const* ptr, size_t bytes)
933{
[241]934 PutArrayTag(1, bytes);
935 PutRawBytes(ptr, bytes);
[219]936}
937
938void
939POutPersist::PutR4 (r_4 val)
940{
[241]941 PutRawByte(PPS_SIMPLE + 4);
942
[219]943 if (bigEndian != IS_BIG_ENDIAN)
944 bswap4(&val);
945
[241]946 PutRawBytes(&val, sizeof(r_4));
[219]947}
948
949void
950POutPersist::PutR4s (r_4 const* tab, size_t n)
951{
[241]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 }
[219]963}
964
965void
966POutPersist::PutR8 (r_8 val)
967{
[241]968 PutRawByte(PPS_SIMPLE + 8);
969
[219]970 if (bigEndian != IS_BIG_ENDIAN)
971 bswap8(&val);
972
[241]973 PutRawBytes(&val, sizeof(r_8));
[219]974}
975
976void
977POutPersist::PutR8s (r_8 const* tab, size_t n)
978{
[241]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 }
[219]990}
991
992void
993POutPersist::PutI2 (int_2 val)
994{
[241]995 PutRawByte(PPS_SIMPLE + 2);
996
[219]997 if (bigEndian != IS_BIG_ENDIAN)
998 bswap2(&val);
999
[241]1000 PutRawBytes(&val, sizeof(int_2));
[219]1001}
1002
1003void
1004POutPersist::PutI2s (int_2 const* tab, size_t n)
1005{
[241]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 }
[219]1017}
1018
1019void
1020POutPersist::PutU2 (uint_2 val)
1021{
[241]1022 PutRawByte(PPS_SIMPLE + 2);
1023
[219]1024 if (bigEndian != IS_BIG_ENDIAN)
1025 bswap2(&val);
1026
[241]1027 PutRawBytes(&val, sizeof(uint_2));
[219]1028}
1029
1030void
1031POutPersist::PutU2s (uint_2 const* tab, size_t n)
1032{
[241]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 }
[219]1044}
1045
1046void
1047POutPersist::PutI4 (int_4 val)
1048{
[241]1049 PutRawByte(PPS_SIMPLE + 4);
1050
[219]1051 if (bigEndian != IS_BIG_ENDIAN)
1052 bswap4(&val);
1053
[241]1054 PutRawBytes(&val, sizeof(int_4));
[219]1055}
1056
1057void
1058POutPersist::PutI4s (int_4 const* tab, size_t n)
1059{
[241]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 }
[219]1071}
1072
1073void
1074POutPersist::PutU4 (uint_4 val)
1075{
[241]1076 PutRawByte(PPS_SIMPLE + 4);
1077
[219]1078 if (bigEndian != IS_BIG_ENDIAN)
1079 bswap4(&val);
1080
[241]1081 PutRawBytes(&val, sizeof(uint_4));
[219]1082}
1083
1084void
1085POutPersist::PutU4s (uint_4 const* tab, size_t n)
1086{
[241]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 }
[219]1098}
1099
1100void
1101POutPersist::PutI8 (int_8 val)
1102{
[241]1103 PutRawByte(PPS_SIMPLE + 8);
1104
[219]1105 if (bigEndian != IS_BIG_ENDIAN)
1106 bswap8(&val);
1107
[241]1108 PutRawBytes(&val, sizeof(int_8));
[219]1109}
1110
1111void
1112POutPersist::PutI8s (int_8 const* tab, size_t n)
1113{
[241]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 }
[219]1125}
1126
1127void
1128POutPersist::PutU8 (uint_8 val)
1129{
[241]1130 PutRawByte(PPS_SIMPLE + 8);
1131
[219]1132 if (bigEndian != IS_BIG_ENDIAN)
1133 bswap8(&val);
1134
[241]1135 PutRawBytes(&val, sizeof(uint_8));
[219]1136}
1137
1138void
1139POutPersist::PutU8s (uint_8 const* tab, size_t n)
1140{
[241]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 }
[219]1152}
1153
1154void
[241]1155POutPersist::PutStr(string const& str)
1156{
1157 PutRawByte(PPS_STRING);
1158 PutRawI2(str.length());
1159 PutRawBytes(str.c_str(), str.length());
1160}
1161
1162void
[219]1163POutPersist::PutLine(char const* ptr, size_t len)
1164{
[241]1165 PutRawByte(PPS_LINE);
1166
[219]1167 if (len == 0) len = strlen(ptr);
[241]1168 PutRawBytes(ptr, len);
1169 PutRawByte('\n');
[219]1170}
1171
[241]1172void
1173POutPersist::PutObject(PPersist const* obj)
1174{
1175 if (serializeNullAndRepeat(obj)) return;
[219]1176
[241]1177 PutRawByte(PPS_OBJECT);
1178 PutRawU8(PIOPersist::Hash(typeid(*obj).name()));
1179 assignObjectId(obj);
1180 obj->WriteSelf(*this);
1181}
[219]1182
[241]1183bool
1184POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1185{
[241]1186 if (x == NULL) {
1187 PutRawByte(PPS_NULL);
1188 return true;
1189 }
[219]1190
[241]1191 int_4 id = findObjectId(x);
1192 if (id >= 0) {
1193 PutRawByte(PPS_REFERENCE);
1194 PutRawI4(id);
1195 return true;
1196 }
[219]1197
[241]1198 return false;
[219]1199}
1200
[241]1201int_4
1202POutPersist::assignObjectId(PPersist const* x)
[219]1203{
[241]1204 int_4 id = objList.size();
1205 objList[x] = id;
1206 return id;
[219]1207}
1208
[241]1209int_4
1210POutPersist::findObjectId(PPersist const* x)
[219]1211{
[241]1212 ObjList::iterator i = objList.find(x);
1213 if (i == objList.end()) return -1;
1214 return (*i).second;
[219]1215}
1216
[241]1217
Note: See TracBrowser for help on using the repository browser.