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

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

reorg exc, ppersist tags...

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