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

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

Compil egcs Reza 23/04/99

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