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

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

ppersist + pexc

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