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

Last change on this file since 1101 was 1101, checked in by ansari, 25 years ago

Compil sous KCC , Reza 26/7/2000

File size: 40.9 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 "ppersist.h"
7#include "anydataobj.h"
8#include <fstream.h>
9#include <iostream.h>
10#include <typeinfo>
11
12
13#ifdef __mac__
14#include "unixmac.h"
15#include <SIOUX.h>
16#endif
17
18// strptime n'est pas defini sous Linux - Reza Mars 2000
19#if defined(OS_LINUX)
20extern "C" {
21char *strptime(char *buf, const char *format, const struct tm *tm);
22}
23#endif
24
25#define MAXTAGLEN 255
26
27//++
28// Class PIOPersist
29// Lib Outils++
30// include ppersist.h
31//
32// Root class for persistant files. Handles the registration of
33// persistant classes
34//--
35
36//++
37// Links See
38// PPersist
39// PInPersist
40// POutPersist
41//--
42
43
44MD5_CONTEXT PIOPersist::ctx;
45PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
46map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
47map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
48
49//++
50void
51PIOPersist::Initialize()
52// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
53//--
54{
55ppclassList = new PIOPersist::ClassList;
56ppclassNameList = new map<string, uint_8>;
57dobjclassNameList = new map<string, uint_8>;
58}
59
60//++
61void
62PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
63//
64// Register a new persistence handler (PPersist) class.
65// The classId is usually a hash of the class name, and
66// ppclass_name is typeid(PPersistClass).name() .
67// This method is called only through the PPersistRegistrar template
68//
69//--
70{
71 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
72 cerr << "RegisterClass : Error, " << hex << classId << dec
73 << " already registered." << endl;
74 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
75 }
76 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
77 cerr << "RegisterClass : Error (2) " << ppclass_name
78 << " already registered." << endl;
79 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
80 }
81
82 (*ppclassList)[classId] = f;
83 (*ppclassNameList)[ppclass_name] = classId;
84}
85
86//++
87void
88PIOPersist::RegisterDataObjClass(uint_8 classId, string class_name)
89// Register a new DataObj class corresponding to a PPersist classId
90// class_typename should be typeid(DataObject).name()
91//--
92{
93 if (ppclassList->find(classId) == ppclassList->end() ) {
94 cerr << "PIOPersist::RegisterDataObjClass() Error (1) "
95 << hex << classId << dec << " Not Found !" << endl;
96 throw( NotFoundExc("PIOPersist::RegisterDataObjClass() Not found classId ") );
97 }
98 if (dobjclassNameList->size() && (dobjclassNameList->find(class_name) != dobjclassNameList->end())) {
99 cerr << "PIOPersist::RegisterDataObjClass() Error (2)" << class_name
100 << " already registered." << endl;
101 throw(DuplicateIdExc("PIOPersist::RegisterDataObjClass() - Already registered"));
102 }
103
104 (*dobjclassNameList)[class_name] = classId;
105}
106
107// class_typename should be typeid(DataObject).name(), to be
108// used by POutPersist::PutDataObject() methods.
109
110PIOPersist::ClassCreatorFunc
111PIOPersist::FindCreatorFunc(uint_8 classId)
112// Returns the PPersist class creator function for the specified classId
113{
114 ClassList::iterator i = ppclassList->find(classId);
115 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
116 return (*i).second;
117}
118
119string
120PIOPersist::getPPClassName(uint_8 classId)
121// Returns the PPersist class name for the specified classId
122{
123 map<string, uint_8>::iterator i;
124 for (i= ppclassNameList->begin(); i != ppclassNameList->end(); i++)
125 if ( (*i).second == classId ) return (*i).first;
126
127 throw(NotFoundExc("PIOPersist::getPPClassName() Not found classId"));
128}
129
130uint_8
131PIOPersist::getPPClassId(string const & typ_name)
132// Returns the classId for the specified PPersist class type name
133{
134 map<string, uint_8>::iterator i = ppclassNameList->find(typ_name);
135 if (i == ppclassNameList->end())
136 throw(NotFoundExc("PIOPersist::getPPClassId() Not found className"));
137 return (*i).second;
138}
139
140uint_8
141PIOPersist::getPPClassId(PPersist const & ppo)
142// Returns the classId for the specified PPersist class
143{
144 string typ_name = typeid(ppo).name() ;
145 return (getPPClassId(typ_name) );
146}
147
148
149string
150PIOPersist::getDataObjClassName(uint_8 classId)
151// Returns the PPersist class name for the specified classId
152{
153 map<string, uint_8>::iterator i;
154 for (i= dobjclassNameList->begin(); i != dobjclassNameList->end(); i++)
155 if ( (*i).second == classId ) return (*i).first;
156
157 throw(NotFoundExc("PIOPersist::getDataObjClassName() Not found classId"));
158}
159
160uint_8
161PIOPersist::getDataObjClassId(string const & typ_name)
162// Returns the classId for the specified PPersist class type name
163{
164 map<string, uint_8>::iterator i = dobjclassNameList->find(typ_name);
165 if (i == dobjclassNameList->end())
166 throw(NotFoundExc("PIOPersist::getDataObjClassId() Not found className"));
167 return (*i).second;
168}
169
170uint_8
171PIOPersist::getDataObjClassId(AnyDataObj const & o)
172// Returns the classId for the specified PPersist class
173{
174 string typ_name = typeid(o).name() ;
175 return (getDataObjClassId(typ_name) );
176}
177
178
179//++
180// Class PPersist
181// Lib Outils++
182// include ppersist.h
183//
184// Classe de base pour des objets persistants. Pour créer un objet
185// persistant :
186// - Hériter de PPersist.
187// - Définir un numéro d'identification de la classe, unique dans Peida
188// - Implémenter "ClassId()"
189// - Implémenter "WriteSelf" et "ReadSelf", qui doivent écrire toutes les variables
190// membres que l'on souhaite écrire, et les relire dans le même ordre.
191// Pour écrire une référence à un objet : l'objet doit être un PPersist,
192// et il suffit d'appeler "Write" sur cet objet, et "PPersistMgr::ReadObject".
193// Si plusieurs objets font référence au même, pour éviter de l'écrire plusieurs
194// fois, il faut que cet objet soit un PShPersist.
195// - Pour que le fichier soit portable, écrire et lire les variables membres en utilisant
196// les fonctions PutXX/GetXX de PInPersist/POutPersist.
197//
198// Attention: les méthodes à redéfinir sont WriteSelf et ReadSelf, mais il ne faut jamais
199// les appeler directement. Seuls Write et Read peuvent être appelées par l'utilisateur.
200//--
201
202//++
203// Links See
204// PInPersist
205// POutPersist
206// PIOPersist
207//--
208
209//++
210void
211PPersist::Write(string const& fn) const
212//
213// Ecrit l'objet dans un nouveau fichier ppersist "fn".
214//--
215{
216 POutPersist of(fn);
217 Write(of);
218}
219
220//++
221void
222PPersist::Read(string const& fn)
223//
224// Relit l'objet dans le fichier ppersist "fn". Il faut connaître a priori
225// le type de l'objet. Pour une relecture avec création automatique du bon
226// objet, utiliser PPersistMgr::ReadObject.
227//--
228{
229 PInPersist inf(fn);
230 Read(inf);
231}
232
233//++
234void
235PPersist::Write(POutPersist& s) const
236//
237// Ecrit l'objet dans le fichier PPersist.
238//--
239{
240 s.PutPPObject(this);
241}
242
243
244//++
245void
246PPersist::Read(PInPersist& s)
247//
248// Relit l'objet dans le fichier ppersist. Il faut connaître a priori
249// le type de l'objet. Pour une relecture avec création automatique du bon
250// objet, utiliser PInPersist::ReadObject.
251// Il faut qu'on soit un objet ecrit
252//--
253{
254 // We should be the exact type
255 // Check tag value
256 unsigned char ppstype,ppstag;
257 s.GetTypeTag(ppstype);
258 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
259 }
260 if (ppstype == PInPersist::PPS_OBJECT) {
261 // Check class id
262 uint_8 classId;
263 s.GetRawU8(classId);
264 uint_8 oid,oid2;
265 s.GetRawU8(oid);
266 if (classId != PIOPersist::getPPClassId(*this) )
267 throw FileFormatExc("PPersist::Read (): not the same object type");
268 ReadSelf(s);
269 // Read the ENDOBJECT
270 s.GetRawUByte(ppstag);
271 if (ppstag != PInPersist::PPS_ENDOBJECT)
272 throw FileFormatExc("PPersist::Read() No PPS_ENDOBJECT tag");
273 s.GetRawU8(oid2);
274 if (oid2 != oid)
275 throw FileFormatExc("PPersist::Read() Inconsistent PPS-OId at PPS_ENDOBJECT ");
276 s.KeepOId(oid, *this); // Object should be kept with its PPS_OId (if oid > 0)
277 }
278 else if ( ppstype == PInPersist::PPS_REFERENCE )
279 s.ReadReference(*this);
280
281 else throw FileFormatExc("PPersist::Read() : not an object in flow");
282
283}
284
285//++
286void
287PPersist::Write(POutPersist& s, string const& tag) const
288//
289// Ecrit l'objet dans le fichier PPersist avec un tag
290//--
291{
292 s.WriteTag(tag);
293 s.PutPPObject(this);
294}
295
296//++
297void
298PPersist::ReadAtTag(PInPersist& s, string const& tag)
299//
300// Lit l'objet à la position du tag numéro "tagid".
301//--
302{
303 if (!s.GotoTag(tag))
304 throw NotFoundExc("PPersist::ReadAtTag tag not found");
305 Read(s);
306}
307
308// Renvoie l'identificateur de l'objet - par defaut=0
309
310uint_8
311PPersist::getMemOId() const
312{
313 return(0);
314}
315
316// Ces deux methodes doivent etre redefinies si getMemOId() renvoie non nul (>0)
317// ShareDataReference() et CloneSharedReference()
318void
319PPersist::ShareDataReference(PPersist & pcs)
320{
321 throw NotAvailableOperation("PPersist::ShareDataReference() - Unsupported operation !");
322}
323
324PPersist *
325PPersist::CloneSharedReference()
326{
327 throw NotAvailableOperation("PPersist::CloneSharedReference() - Unsupported operation !");
328}
329
330//++
331// virtual void PPersist::ReadSelf(PInPersist&)=0
332// Méthode virtuelle pure à redéfinir. Elle est appelée par Read
333// et PPersistMgr::ReadObject. Il faut relire les variables membres,
334// dans l'ordre où elles ont été écrites par WriteSelf.
335// virtual void PPersist::WriteSelf(POutPersist&) const=0
336// Méthode virtuelle pure à redéfinir. Elle est appelée par Write.
337// Il faut écrire les variables membres,
338// dans l'ordre où elles seront relues par ReadSelf.
339//--
340
341
342
343//++
344// Class PInPersist
345// Lib Outils++
346// include ppersist.h
347//
348// Fichier d'objets persistants, en lecture.
349//--
350
351//++
352PInPersist::PInPersist(string const& flnm, bool scan)
353//
354// Constructeur. Ouvre le fichier.
355//--
356{
357 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
358
359 // Read and check header
360
361 char rbuf[36];
362 GetRawBytes(rbuf, 32);
363 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
364 throw FileFormatExc("PInPersist::PInPersist bad header");
365 }
366 rbuf[32] = '\0';
367 version = atoi(rbuf+25);
368 if (version < 2) {
369 cerr << "PInPersist::PInPersist(" << flnm << ") Version(=" << version
370 << ") < 2 not supported !" << endl;
371 throw FileFormatExc("PInPersist::PInPersist() - Unsupported (Old) Version");
372 }
373 // read endianness
374 GetRawBytes(rbuf, 32);
375 if (strncmp(rbuf,"BIG-ENDIAN",10) == 0)
376 bigEndian = true;
377 else if (strncmp(rbuf,"LITTLE-ENDIAN",13) == 0)
378 bigEndian = false;
379 else {
380 throw FileFormatExc("PInPersist::PInPersist bad header - endianness");
381 }
382
383 // read creation date
384 GetRawBytes(rbuf, 32);
385 rbuf[32] = '\0';
386 struct tm tm;
387 #ifndef __MWERKS__
388 strptime(rbuf,"%d/%m/%Y %H:%M:%S GMT",&tm);
389 #else
390 sscanf(rbuf,"%2d/%2d/%4d %2d:%2d:%2d GMT",&tm.tm_mday,&tm.tm_mon,&tm.tm_year,
391 &tm.tm_hour,&tm.tm_min,&tm.tm_sec);
392 tm.tm_mon --;
393 tm.tm_year -= 1900;
394 #endif
395 creationdate = mktime(&tm);
396 filename = flnm; // keep the filename
397 seqread = true; // To flag non sequential reads
398 if (scan) Scan();
399}
400
401
402
403PInPersist::~PInPersist()
404{
405 ObjList::iterator i;
406 for(i=objList.begin(); i!= objList.end(); i++)
407 if ((*i).second) delete (*i).second;
408 delete s;
409}
410
411
412string
413PInPersist::CreationDateStr()
414{
415 time_t cdt = CreationDate();
416 string cdate = ctime(&cdt);
417 return(cdate);
418}
419
420void
421PInPersist::Scan()
422{
423 // On cherche la liste des tags, a la fin du fichier
424
425 unsigned char ppstype;
426 size_t debut;
427#ifdef STREAMPOS_IS_CLASS
428 debut = s->tellg().offset();
429#else
430 debut = s->tellg();
431#endif
432
433 // Find tag entries at end of file
434#if defined(Linux) && defined(__GNUG__)
435 // There seems to be a bug where seekg with ios::end under Linux with g++
436 // So, we use seek with ios::beg
437 s->seekg(0, ios::end);
438 int_8 tagpos = s->tellg() - (sizeof(int_8)+1);
439 s->seekg(tagpos, ios::beg);
440#else
441 s->seekg(-(sizeof(int_8)+1), ios::end);
442#endif
443
444 GetTypeTag(ppstype);
445 if (ppstype != PPS_EOF)
446 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
447
448 int_8 pos;
449 GetRawI8(pos);
450 if (pos < 0) { // no tags
451 s->seekg(debut);
452 return;
453 }
454
455 char buffer[MAXTAGLEN+1];
456 s->seekg(pos);
457 while (true) {
458 GetTypeTag(ppstype);
459 if (ppstype == PPS_EOF) break;
460
461 if (ppstype != PPS_TAG)
462 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
463
464 GetRawI8(pos);
465 int_4 len;
466 GetRawI4(len);
467 if (len > MAXTAGLEN)
468 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
469 GetRawBytes(buffer, len);
470 buffer[len] = '\0';
471
472 tags[buffer] = pos;
473 }
474 s->seekg(debut);
475}
476
477
478int
479PInPersist::NbTags()
480{
481 return tags.size();
482}
483
484bool
485PInPersist::GotoTag(string const& name)
486{
487 map<string, int_8>::iterator i = tags.find(name);
488 if (i == tags.end())
489 return false;
490 // throw NotFoundExc("PInPersist::GotoTag tag not found");
491 s->seekg((*i).second);
492 seqread = false;
493 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
494 return(true);
495}
496
497bool
498PInPersist::GotoTagNum(int itag)
499{
500 if (itag<0 || itag >= (int)tags.size()) return false;
501 map<string, int_8>::iterator i = tags.begin();
502 for (int j=0; j<itag; j++) i++;
503 s->seekg((*i).second);
504 seqread = false;
505 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
506 return(true);
507}
508
509string
510PInPersist::GetTagName(int itag)
511{
512 if (itag<0 || itag >= (int)tags.size()) return "";
513 map<string, int_8>::iterator i = tags.begin();
514 for (int j=0; j<itag; j++) i++;
515 return((*i).first);
516}
517
518string
519PInPersist::GetTagClassName(int itag)
520{
521 // A faire
522// if (itag<0 || itag >= (int)tags.size()) return "";
523// map<string, int_8>::iterator i = tags.begin();
524// for (int j=0; j<itag; j++) i++;
525// uint_8 cid = (*i).second;
526// return(GetClassName(cid));
527 return("");
528}
529
530static vector<string> * ret_tag_names = NULL;
531vector<string> const &
532PInPersist::GetTagNames()
533{
534if (ret_tag_names) delete ret_tag_names;
535ret_tag_names = new vector<string> ;
536map<string, int_8>::iterator i;
537for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
538return(*ret_tag_names);
539}
540
541//++
542// void PInPersist::GetByte(char& c)
543// void PInPersist::GetBytes(void* ptr, size_t bytes)
544// void PInPersist::GetR4 (r_4& result)
545// void PInPersist::GetR4s (r_4* tab, size_t n)
546// void PInPersist::GetR8 (r_8& result)
547// void PInPersist::GetR8s (r_8* tab, size_t n)
548// void PInPersist::GetI2 (int_2& result)
549// void PInPersist::GetI2s (int_2* tab, size_t n)
550// void PInPersist::GetU2 (uint_2& result)
551// void PInPersist::GetU2s (uint_2* tab, size_t n)
552// void PInPersist::GetI4 (int_4& result)
553// void PInPersist::GetI4s (int_4* tab, size_t n)
554// void PInPersist::GetU4 (uint_4& result)
555// void PInPersist::GetU4s (uint_4* tab, size_t n)
556// void PInPersist::GetI8 (int_8& result)
557// void PInPersist::GetI8s (int_8* tab, size_t n)
558// void PInPersist::GetU8 (uint_8& result)
559// void PInPersist::GetU8s (uint_8* tab, size_t n)
560// Lecture de données portables depuis le fichier PPersist. Pour chaque type
561// de données, on peut lire une valeur, ou un tableau de valeurs.
562// void PInPersist::GetLine(char* ptr, size_t len)
563// Lecture d'une ligne de texte depuis le fichier PPersist.
564//--
565
566
567static inline void bswap8(void* p)
568{
569 uint_8 tmp = *(uint_8*)p;
570 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
571 ((tmp >> (5*8)) & 0x0000FF00) |
572 ((tmp >> (3*8)) & 0x00FF0000) |
573 ((tmp >> (1*8)) & 0xFF000000) |
574 ((tmp & 0xFF000000) << (1*8)) |
575 ((tmp & 0x00FF0000) << (3*8)) |
576 ((tmp & 0x0000FF00) << (5*8)) |
577 ((tmp & 0x000000FF) << (7*8));
578}
579
580static inline void bswap4(void* p)
581{
582 uint_4 tmp = *(uint_4*)p;
583 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
584 ((tmp >> 8) & 0x0000FF00) |
585 ((tmp & 0x0000FF00) << 8) |
586 ((tmp & 0x000000FF) << 24);
587}
588
589static inline void bswap2(void* p)
590{
591 uint_2 tmp = *(uint_2*)p;
592 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
593 ((tmp & 0x00FF) << 8);
594}
595
596void
597PInPersist::GetTypeTag(unsigned char& c)
598{
599 c = PPS_TAG_MARK;
600 while (c == PPS_TAG_MARK) GetRawUByte(c);
601 // while (c == PPS_TAG_MARK) { Il ne faut plus faire ca !
602 // objList.clear(); $CHECK$ Reza 03/2000
603 // GetRawByte(c);
604 // }
605}
606
607
608void
609PInPersist::GetRawByte(char& c)
610{
611 GetRawBytes(&c, 1);
612}
613
614void
615PInPersist::GetRawUByte(unsigned char& c)
616{
617 GetRawBytes(&c, 1);
618}
619
620void
621PInPersist::GetRawBytes(void* ptr, size_t bytes)
622{
623 s->read((char*)ptr, bytes);
624}
625
626void
627PInPersist::GetRawI2 (int_2& result)
628{
629 GetRawBytes(&result, sizeof(int_2));
630 if (bigEndian != IS_BIG_ENDIAN)
631 bswap2(&result);
632}
633
634void
635PInPersist::GetRawI4 (int_4& result)
636{
637 GetRawBytes(&result, sizeof(int_4));
638 if (bigEndian != IS_BIG_ENDIAN)
639 bswap4(&result);
640}
641
642void
643PInPersist::GetRawI8 (int_8& result)
644{
645 GetRawBytes(&result, sizeof(int_8));
646 if (bigEndian != IS_BIG_ENDIAN)
647 bswap8(&result);
648}
649
650void
651PInPersist::GetRawU8 (uint_8& result)
652{
653 GetRawBytes(&result, sizeof(uint_8));
654 if (bigEndian != IS_BIG_ENDIAN)
655 bswap8(&result);
656}
657
658void
659PInPersist::CheckTag(short datasz, short datatype)
660// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
661{
662 unsigned char ppstype;
663 GetTypeTag(ppstype);
664 if (ppstype != PPS_SIMPLE + datasz + datatype)
665 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
666}
667
668void
669PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
670// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
671{
672 unsigned char ppstype;
673 GetTypeTag(ppstype);
674 size_t filesz;
675 if (sz <= 0x7fffffff) {
676 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
677 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
678 int_4 ff;
679 GetRawI4(ff); filesz=ff;
680 } else {
681 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
682 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
683 uint_8 ff;
684 GetRawU8(ff); filesz=ff;
685 }
686 if (filesz != sz)
687 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
688}
689
690void
691PInPersist::GetByte(char& c)
692{
693 CheckTag(1,PPS_DATATYPE_CHAR);
694 GetRawBytes(&c, 1);
695}
696
697
698void
699PInPersist::GetBytes(void* ptr, size_t bytes)
700{
701 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
702 GetRawBytes(ptr, bytes);
703}
704void
705PInPersist::GetR4 (r_4& result)
706{
707 CheckTag(4,PPS_DATATYPE_FLOAT);
708 GetRawBytes(&result, sizeof(r_4));
709 if (bigEndian != IS_BIG_ENDIAN)
710 bswap4(&result);
711}
712
713
714void
715PInPersist::GetR4s (r_4* tab, size_t n)
716{
717 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
718 GetRawBytes(tab, n*sizeof(r_4));
719 if (bigEndian == IS_BIG_ENDIAN) return;
720
721 for (unsigned int i=0; i<n; i++)
722 bswap4(tab+i);
723
724 return;
725}
726
727void
728PInPersist::GetR8 (r_8& result)
729{
730 CheckTag(8,PPS_DATATYPE_FLOAT);
731 GetRawBytes(&result, sizeof(r_8));
732 if (bigEndian != IS_BIG_ENDIAN)
733 bswap8(&result);
734}
735
736void
737PInPersist::GetR8s (r_8* tab, size_t n)
738{
739 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
740 GetRawBytes(tab, n*sizeof(r_8));
741 if (bigEndian == IS_BIG_ENDIAN) return;
742
743 for (unsigned int i=0; i<n; i++)
744 bswap8(tab+i);
745
746 return;
747}
748
749void
750PInPersist::GetI2 (int_2& result)
751{
752 CheckTag(2,PPS_DATATYPE_INTEGER);
753 GetRawBytes(&result, sizeof(int_2));
754 if (bigEndian != IS_BIG_ENDIAN)
755 bswap2(&result);
756}
757
758void
759PInPersist::GetI2s (int_2* tab, size_t n)
760{
761 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
762 GetRawBytes(tab, n*sizeof(int_2));
763 if (bigEndian == IS_BIG_ENDIAN) return;
764
765 for (unsigned int i=0; i<n; i++)
766 bswap2(tab+i);
767
768 return;
769}
770
771void
772PInPersist::GetU2 (uint_2& result)
773{
774 CheckTag(2,PPS_DATATYPE_UNSIGNED);
775 GetRawBytes(&result, sizeof(uint_2));
776 if (bigEndian != IS_BIG_ENDIAN)
777 bswap2(&result);
778}
779
780void
781PInPersist::GetU2s (uint_2* tab, size_t n)
782{
783 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
784 GetRawBytes(tab, n*sizeof(uint_2));
785 if (bigEndian == IS_BIG_ENDIAN) return;
786
787 for (unsigned int i=0; i<n; i++)
788 bswap2(tab+i);
789
790 return;
791}
792
793void
794PInPersist::GetI4 (int_4& result)
795{
796 CheckTag(4,PPS_DATATYPE_INTEGER);
797 GetRawBytes(&result, sizeof(int_4));
798 if (bigEndian != IS_BIG_ENDIAN)
799 bswap4(&result);
800}
801
802void
803PInPersist::GetI4s (int_4* tab, size_t n)
804{
805 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
806 GetRawBytes(tab, n*sizeof(int_4));
807 if (bigEndian == IS_BIG_ENDIAN) return;
808
809 for (unsigned int i=0; i<n; i++)
810 bswap4(tab+i);
811
812 return;
813}
814
815void
816PInPersist::GetU4 (uint_4& result)
817{
818 CheckTag(4,PPS_DATATYPE_UNSIGNED);
819 GetRawBytes(&result, sizeof(uint_4));
820 if (bigEndian != IS_BIG_ENDIAN)
821 bswap4(&result);
822}
823
824void
825PInPersist::GetU4s (uint_4* tab, size_t n)
826{
827 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
828 GetRawBytes(tab, n*sizeof(uint_4));
829 if (bigEndian == IS_BIG_ENDIAN) return;
830
831 for (unsigned int i=0; i<n; i++)
832 bswap4(tab+i);
833
834 return;
835}
836
837
838void
839PInPersist::GetI8 (int_8& result)
840{
841 CheckTag(8,PPS_DATATYPE_INTEGER);
842 GetRawBytes(&result, sizeof(int_8));
843 if (bigEndian != IS_BIG_ENDIAN)
844 bswap8(&result);
845}
846
847void
848PInPersist::GetI8s (int_8* tab, size_t n)
849{
850 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
851 GetRawBytes(tab, n*sizeof(int_8));
852 if (bigEndian == IS_BIG_ENDIAN) return;
853
854 for (unsigned int i=0; i<n; i++)
855 bswap8(tab+i);
856
857 return;
858}
859
860void
861PInPersist::GetU8 (uint_8& result)
862{
863 CheckTag(8,PPS_DATATYPE_UNSIGNED);
864 GetRawBytes(&result, sizeof(uint_8));
865 if (bigEndian != IS_BIG_ENDIAN)
866 bswap8(&result);
867}
868
869void
870PInPersist::GetU8s (uint_8* tab, size_t n)
871{
872 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
873 GetRawBytes(tab, n*sizeof(uint_8));
874 if (bigEndian == IS_BIG_ENDIAN) return;
875
876 for (unsigned int i=0; i<n; i++)
877 bswap8(tab+i);
878
879 return;
880}
881
882
883void
884PInPersist::GetLine(char* ptr, size_t len)
885{
886 string str;
887 GetStr(str);
888 strncpy(ptr, str.c_str(), len);
889 ptr[len] = '\0';
890}
891
892void
893PInPersist::GetStr(string& str)
894{
895 unsigned char ppstype;
896 GetTypeTag(ppstype);
897 if (ppstype != PPS_STRING)
898 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
899 int_4 len;
900 GetRawI4(len);
901 char * buff = new char[len+1];
902 GetRawBytes(buff, len);
903 buff[len] = '\0';
904 str = buff;
905 delete[] buff;
906}
907
908
909PPersist*
910PInPersist::ReadObject()
911{
912 return(GetPPObject());
913}
914
915void
916PInPersist::GetObject(AnyDataObj & o)
917{
918 GetPPObject(&o);
919 return;
920}
921
922void
923PInPersist::GetObject(AnyDataObj & o, string tagname)
924{
925 GotoTag(tagname);
926 GetPPObject(&o);
927 return;
928}
929
930PPersist*
931PInPersist::GetPPObject(AnyDataObj * po)
932{
933 // Get tag
934 unsigned char ppstype;
935 GetTypeTag(ppstype);
936 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
937 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
938 }
939
940 if (ppstype == PPS_NULL) {
941 return NULL;
942 } else if (ppstype == PPS_OBJECT) {
943 // Get class id
944 uint_8 classId;
945 GetRawU8(classId);
946 uint_8 oid,oid2;
947 GetRawU8(oid);
948
949 // Get factory method
950 ClassCreatorFunc f = FindCreatorFunc(classId);
951 if (!f) {
952 throw NotFoundExc("PInPersist::ReadObject class not registered");
953 }
954
955 // Create object
956 PPersist* object = f();
957 // If a DataObject was specified , we assign it to the PPersistObject
958 if (po != NULL) object->SetDataObj(*po);
959
960 object->ReadSelf(*this);
961 unsigned char ppstag;
962 // Read the ENDOBJECT
963 GetRawUByte(ppstag);
964 if (ppstag != PPS_ENDOBJECT)
965 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
966 GetRawU8(oid2);
967 if (oid2 != oid)
968 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
969
970 KeepOId(oid, *object);
971 return object;
972 }
973 else if (ppstype == PPS_REFERENCE)
974 return ReadReference();
975
976 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
977}
978
979
980void
981PInPersist::AnalyseTags(int lev)
982{
983 unsigned char ppstag=0;
984 unsigned char ppst1,ppst2,ppst3;
985 uint_8 cpos,fsize;
986 uint_8 ui8,cid,oid;
987 int_4 i4;
988 int_8 i8;
989 char * buff;
990 string str;
991
992 cout << "\n ---------------------------------------------------------- " << endl;
993 cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl;
994
995
996#ifdef STREAMPOS_IS_CLASS
997 cpos = s->tellg().offset();
998#else
999 cpos = s->tellg();
1000#endif
1001 s->seekg(0,ios::end);
1002#ifdef STREAMPOS_IS_CLASS
1003 fsize = s->tellg().offset();
1004#else
1005 fsize = s->tellg();
1006#endif
1007 s->seekg(cpos,ios::beg);
1008
1009 cout << " Version= " << Version() << " FileSize= " << fsize
1010 << " Creation Date= " << CreationDateStr() << endl;
1011
1012 uint_8 totntags = 0;
1013 bool eofok = false;
1014
1015 while ( (ppstag != PPS_EOF) && (cpos < fsize) ) {
1016#ifdef STREAMPOS_IS_CLASS
1017 cpos = s->tellg().offset();
1018#else
1019 cpos = s->tellg();
1020#endif
1021 GetRawUByte(ppstag);
1022 totntags++;
1023
1024 ppst1 = ppstag&0x0f; // bits 0123
1025 ppst2 = ppstag&0x30; // bits 45
1026 ppst3 = ppstag&0xc0; // bits 67
1027 if ((ppst2 == 0) && (ppst3 == 0) ) {
1028 switch (ppst1) {
1029
1030 case PPS_NULL :
1031 if (lev > 1) cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
1032 break;
1033
1034 case PPS_STRING :
1035 GetRawI4(i4);
1036 if (lev > 1) cout << "<PPS_STRING> tag at position " << hex << cpos << dec
1037 << " Length=" << i4 << endl;
1038 s->seekg(i4,ios::cur);
1039 break;
1040
1041 case PPS_OBJECT :
1042 GetRawU8(cid);
1043 GetRawU8(oid);
1044 cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid
1045 << " ObjectId= " << oid << dec << endl;
1046 break;
1047
1048 case PPS_REFERENCE :
1049 GetRawU8(oid);
1050 GetRawI8(i8);
1051 cout << "<PPS_REFERENCE> tag at position " << hex << cpos << " ObjectId= "
1052 << oid << " OrigPos=" << i8 << dec << endl;
1053 break;
1054
1055 case PPS_TAG_MARK :
1056 cout << "<PPS_TAG_MARK> tag at position " << hex << cpos << dec << endl;
1057 break;
1058
1059 case PPS_ENDOBJECT :
1060 GetRawU8(oid);
1061 cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << " ObjectId= "
1062 << oid << dec << endl;
1063 break;
1064
1065 case PPS_TAG :
1066 GetRawI8(i8);
1067 GetRawI4(i4);
1068 buff = new char[i4+1];
1069 GetRawBytes(buff, i4);
1070 buff[i4] = '\0'; str = buff;
1071 delete[] buff;
1072 cout << "<PPS_TAG> tag at position " << hex << cpos << dec
1073 << " Name= " << str << endl;
1074 break;
1075
1076 case PPS_EOF :
1077 GetRawI8(i8);
1078 cout << "<PPS_EOF> tag at position " << hex << cpos
1079 << " TagPos=" << i8 << dec << endl;
1080 eofok = true;
1081 break;
1082
1083 default :
1084 cerr << " ERROR : Unexpected tag value " << hex << ppstag
1085 << " At position" << cpos << dec << endl;
1086 throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
1087 }
1088 }
1089 else {
1090 string dtype = "???? x";
1091 if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
1092 else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
1093 else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
1094 else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
1095 int_4 dsize = ppst1;
1096 char sb[16];
1097 sprintf(sb, "%d", dsize);
1098 dtype += sb;
1099
1100 switch (ppst2) {
1101
1102 case PPS_SIMPLE :
1103 if (lev > 2) cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec
1104 << " DataType=" << dtype << endl;
1105 s->seekg(dsize, ios::cur);
1106 break;
1107
1108 case PPS_SIMPLE_ARRAY4 :
1109 GetRawI4(i4);
1110 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec
1111 << " DataType=" << dtype << " NElts= " << i4 << endl;
1112 s->seekg((uint_8)dsize*(uint_8)i4, ios::cur);
1113 break;
1114
1115 case PPS_SIMPLE_ARRAY8 :
1116 GetRawU8(ui8);
1117 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec
1118 << " DataType=" << dtype << " NElts= " << ui8 << endl;
1119 s->seekg((uint_8)dsize*ui8, ios::cur);
1120 break;
1121 }
1122 }
1123 }
1124 if (!eofok)
1125 throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
1126
1127 cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl;
1128 cout << " ---------------------------------------------------------- \n" << endl;
1129 return;
1130}
1131
1132void
1133PInPersist::ReadReference(PPersist & ppo)
1134{
1135 PPersist * pr = ReadReference();
1136 ppo.ShareDataReference(*pr);
1137}
1138
1139
1140PPersist *
1141PInPersist::ReadReference()
1142{
1143 uint_8 oid;
1144 int_8 pos;
1145 GetRawU8(oid);
1146 GetRawI8(pos);
1147 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
1148 map<uint_8, PPersist *>::iterator i = objList.find(oid);
1149 if (i != objList.end()) return (*i).second;
1150 else { // We may have skeeped it !
1151 // Let's try to read it
1152 int_8 cpos;
1153#ifdef STREAMPOS_IS_CLASS
1154 cpos = s->tellg().offset();
1155#else
1156 cpos = s->tellg();
1157#endif
1158 s->seekg(pos);
1159 PPersist* ppo = ReadObject();
1160 s->seekg(cpos);
1161 delete ppo;
1162 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
1163
1164 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
1165 if (i2 == objList.end())
1166 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
1167 return (*i2).second;
1168 }
1169}
1170
1171
1172void
1173PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
1174{
1175 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
1176 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
1177 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
1178 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoTag)
1179 // et pas avec une lecture sequentielle ... Reza 03/2000
1180 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
1181 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
1182 PPersist *pp = (*objList.find(oid)).second;
1183 ppo.ShareDataReference(*pp);
1184 }
1185 else {
1186 PPersist * npp = ppo.CloneSharedReference();
1187 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
1188 objList[oid] = npp;
1189 }
1190 return;
1191}
1192
1193//++
1194// Class POutPersist
1195// Lib Outils++
1196// include ppersist.h
1197//
1198// Fichier d'objets persistants, en écriture.
1199//--
1200
1201
1202//++
1203// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
1204//
1205// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
1206// sur machines petit-boutiennes, et gros-boutien sur machines
1207// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
1208// ou PPersist::PPS_BIG_ENDIAN.
1209//--
1210POutPersist::POutPersist(string const& flnm, int endianness)
1211{
1212 if (endianness == -1)
1213 bigEndian = IS_BIG_ENDIAN;
1214 else
1215 bigEndian = endianness;
1216
1217 // PPS (POutPersist stream) Object Id initialisation
1218 pps_OId = 0;
1219 // Output stream creation
1220 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
1221
1222 // Header
1223 PutRawBytes("SOS-SOPHYA-PPersistFile V2 ",32);
1224 PutRawBytes(bigEndian
1225 ? "BIG-ENDIAN "
1226 : "LITTLE-ENDIAN ",32);
1227
1228// ---- GMT creation date of the file
1229 time_t tm = time(NULL);
1230 char datestring[33];
1231 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
1232 for(int i=l; i<32; i++) datestring[i] = ' ';
1233 datestring[32] = '\0';
1234 PutRawBytes(datestring, 32);
1235 filename = flnm;
1236}
1237
1238POutPersist::~POutPersist()
1239{
1240 if (tags.size() == 0) {
1241 PutRawUByte(PPS_EOF);
1242 PutRawI8(-1);
1243 } else {
1244 int_8 tagPos;
1245#ifdef STREAMPOS_IS_CLASS
1246 tagPos = s->tellp().offset();
1247#else
1248 tagPos = s->tellp();
1249#endif
1250 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
1251 string name = (*i).first;
1252 int_8 pos = (*i).second;
1253 PutRawUByte(PPS_TAG); // This is a tag
1254 PutRawI8(pos); // position of previous tag
1255 PutRawI4(name.length()); // length of the name
1256 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
1257 }
1258 PutRawUByte(PPS_EOF);
1259 PutRawI8(tagPos);
1260 }
1261
1262 delete s; // Close the stream
1263}
1264
1265
1266void
1267POutPersist::WriteTag(string const& name)
1268{
1269 if (name.length() > MAXTAGLEN)
1270 throw ParmError("POutPersist::WriteTag tag name too long");
1271
1272 if (tags.find(name) != tags.end())
1273 throw DuplicateIdExc("POutPersist::WriteTag duplicate tag name");
1274
1275 // Get current file position
1276 int_8 tagPos;
1277
1278 #ifdef STREAMPOS_IS_CLASS
1279 tagPos = s->tellp().offset();
1280 #else
1281 tagPos = s->tellp();
1282 #endif
1283
1284 tags[name] = tagPos;
1285 PutRawUByte(PPS_TAG_MARK); // This is a tag
1286 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
1287}
1288
1289//++
1290// void POutPersist::PutByte(char& c)
1291// void POutPersist::PutBytes(void const* ptr, size_t bytes)
1292// void POutPersist::PutR4 (r_4 result)
1293// void POutPersist::PutR4s (r_4 const* tab, size_t n)
1294// void POutPersist::PutR8 (r_8 result)
1295// void POutPersist::PutR8s (r_8 const* tab, size_t n)
1296// void POutPersist::PutI2 (int_2 result)
1297// void POutPersist::PutI2s (int_2 const* tab, size_t n)
1298// void POutPersist::PutU2 (uint_2 result)
1299// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
1300// void POutPersist::PutI4 (int_4 result)
1301// void POutPersist::PutI4s (int_4 const* tab, size_t n)
1302// void POutPersist::PutU4 (uint_4 result)
1303// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
1304// void POutPersist::PutI8 (int_8 result)
1305// void POutPersist::PutI8s (int_8 const* tab, size_t n)
1306// void POutPersist::PutU8 (uint_8 result)
1307// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
1308// void POutPersist::PutStr (string const&)
1309// Ecriture de données portables.. Pour chaque type
1310// de données, on peut écrire une valeur, ou un tableau de valeurs.
1311// void POutPersist::PutLine(char const* ptr, size_t len)
1312// Ecriture d'une ligne de texte dans le fichier PPersist.
1313//--
1314
1315
1316
1317
1318void
1319POutPersist::PutRawBytes(void const* ptr, size_t bytes)
1320{
1321 s->write((char const*)ptr, bytes);
1322}
1323
1324void
1325POutPersist::PutRawByte(char c)
1326{
1327 PutRawBytes(&c, 1);
1328}
1329
1330void
1331POutPersist::PutRawUByte(unsigned char c)
1332{
1333 PutRawBytes(&c, 1);
1334}
1335
1336void
1337POutPersist::PutRawI2 (int_2 val)
1338{
1339 if (bigEndian != IS_BIG_ENDIAN)
1340 bswap2(&val);
1341
1342 PutRawBytes(&val, sizeof(int_2));
1343}
1344
1345void
1346POutPersist::PutRawI4 (int_4 val)
1347{
1348 if (bigEndian != IS_BIG_ENDIAN)
1349 bswap4(&val);
1350
1351 PutRawBytes(&val, sizeof(int_4));
1352}
1353
1354void
1355POutPersist::PutRawI8 (int_8 val)
1356{
1357 if (bigEndian != IS_BIG_ENDIAN)
1358 bswap8(&val);
1359
1360 PutRawBytes(&val, sizeof(int_8));
1361}
1362
1363void
1364POutPersist::PutRawU8 (uint_8 val)
1365{
1366 if (bigEndian != IS_BIG_ENDIAN)
1367 bswap8(&val);
1368
1369 PutRawBytes(&val, sizeof(uint_8));
1370}
1371
1372void
1373POutPersist::PutArrayTag(short datasz, size_t sz, short datatype)
1374// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
1375{
1376 if (sz <= 0x7fffffff) {
1377 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
1378 PutRawI4(sz);
1379 } else {
1380 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
1381 PutRawU8(sz);
1382 }
1383}
1384
1385void
1386POutPersist::PutByte(char c)
1387{
1388 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
1389 PutRawBytes(&c, 1);
1390}
1391
1392
1393
1394void
1395POutPersist::PutBytes(void const* ptr, size_t bytes)
1396{
1397 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
1398 PutRawBytes(ptr, bytes);
1399}
1400
1401void
1402POutPersist::PutR4 (r_4 val)
1403{
1404 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
1405
1406 if (bigEndian != IS_BIG_ENDIAN)
1407 bswap4(&val);
1408
1409 PutRawBytes(&val, sizeof(r_4));
1410}
1411
1412void
1413POutPersist::PutR4s (r_4 const* tab, size_t n)
1414{
1415 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
1416
1417 if (bigEndian == IS_BIG_ENDIAN) {
1418 PutRawBytes(tab, n*sizeof(r_4));
1419 } else {
1420 for (unsigned int i=0; i<n; i++) {
1421 r_4 val = tab[i];
1422 bswap4(&val);
1423 PutRawBytes(&val, sizeof(r_4));
1424 }
1425 }
1426}
1427
1428void
1429POutPersist::PutR8 (r_8 val)
1430{
1431 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
1432
1433 if (bigEndian != IS_BIG_ENDIAN)
1434 bswap8(&val);
1435
1436 PutRawBytes(&val, sizeof(r_8));
1437}
1438
1439void
1440POutPersist::PutR8s (r_8 const* tab, size_t n)
1441{
1442 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
1443
1444 if (bigEndian == IS_BIG_ENDIAN) {
1445 PutRawBytes(tab, n*sizeof(r_8));
1446 } else {
1447 for (unsigned int i=0; i<n; i++) {
1448 r_8 val = tab[i];
1449 bswap8(&val);
1450 PutRawBytes(&val, sizeof(r_8));
1451 }
1452 }
1453}
1454
1455void
1456POutPersist::PutI2 (int_2 val)
1457{
1458 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
1459
1460 if (bigEndian != IS_BIG_ENDIAN)
1461 bswap2(&val);
1462
1463 PutRawBytes(&val, sizeof(int_2));
1464}
1465
1466void
1467POutPersist::PutI2s (int_2 const* tab, size_t n)
1468{
1469 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
1470
1471 if (bigEndian == IS_BIG_ENDIAN) {
1472 PutRawBytes(tab, n*sizeof(int_2));
1473 } else {
1474 for (unsigned int i=0; i<n; i++) {
1475 int_2 val = tab[i];
1476 bswap2(&val);
1477 PutRawBytes(&val, sizeof(int_2));
1478 }
1479 }
1480}
1481
1482void
1483POutPersist::PutU2 (uint_2 val)
1484{
1485 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
1486
1487 if (bigEndian != IS_BIG_ENDIAN)
1488 bswap2(&val);
1489
1490 PutRawBytes(&val, sizeof(uint_2));
1491}
1492
1493void
1494POutPersist::PutU2s (uint_2 const* tab, size_t n)
1495{
1496 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
1497
1498 if (bigEndian == IS_BIG_ENDIAN) {
1499 PutRawBytes(tab, n*sizeof(uint_2));
1500 } else {
1501 for (unsigned int i=0; i<n; i++) {
1502 uint_2 val = tab[i];
1503 bswap2(&val);
1504 PutRawBytes(&val, sizeof(uint_2));
1505 }
1506 }
1507}
1508
1509void
1510POutPersist::PutI4 (int_4 val)
1511{
1512 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
1513
1514 if (bigEndian != IS_BIG_ENDIAN)
1515 bswap4(&val);
1516
1517 PutRawBytes(&val, sizeof(int_4));
1518}
1519
1520void
1521POutPersist::PutI4s (int_4 const* tab, size_t n)
1522{
1523 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
1524
1525 if (bigEndian == IS_BIG_ENDIAN) {
1526 PutRawBytes(tab, n*sizeof(int_4));
1527 } else {
1528 for (unsigned int i=0; i<n; i++) {
1529 int_4 val = tab[i];
1530 bswap4(&val);
1531 PutRawBytes(&val, sizeof(int_4));
1532 }
1533 }
1534}
1535
1536void
1537POutPersist::PutU4 (uint_4 val)
1538{
1539 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
1540
1541 if (bigEndian != IS_BIG_ENDIAN)
1542 bswap4(&val);
1543
1544 PutRawBytes(&val, sizeof(uint_4));
1545}
1546
1547void
1548POutPersist::PutU4s (uint_4 const* tab, size_t n)
1549{
1550 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
1551
1552 if (bigEndian == IS_BIG_ENDIAN) {
1553 PutRawBytes(tab, n*sizeof(uint_4));
1554 } else {
1555 for (unsigned int i=0; i<n; i++) {
1556 uint_4 val = tab[i];
1557 bswap4(&val);
1558 PutRawBytes(&val, sizeof(uint_4));
1559 }
1560 }
1561}
1562
1563void
1564POutPersist::PutI8 (int_8 val)
1565{
1566 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
1567
1568 if (bigEndian != IS_BIG_ENDIAN)
1569 bswap8(&val);
1570
1571 PutRawBytes(&val, sizeof(int_8));
1572}
1573
1574void
1575POutPersist::PutI8s (int_8 const* tab, size_t n)
1576{
1577 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
1578
1579 if (bigEndian == IS_BIG_ENDIAN) {
1580 PutRawBytes(tab, n*sizeof(int_8));
1581 } else {
1582 for (unsigned int i=0; i<n; i++) {
1583 int_8 val = tab[i];
1584 bswap8(&val);
1585 PutRawBytes(&val, sizeof(int_8));
1586 }
1587 }
1588}
1589
1590void
1591POutPersist::PutU8 (uint_8 val)
1592{
1593 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
1594
1595 if (bigEndian != IS_BIG_ENDIAN)
1596 bswap8(&val);
1597
1598 PutRawBytes(&val, sizeof(uint_8));
1599}
1600
1601void
1602POutPersist::PutU8s (uint_8 const* tab, size_t n)
1603{
1604 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
1605
1606 if (bigEndian == IS_BIG_ENDIAN) {
1607 PutRawBytes(tab, n*sizeof(uint_8));
1608 } else {
1609 for (unsigned int i=0; i<n; i++) {
1610 uint_8 val = tab[i];
1611 bswap8(&val);
1612 PutRawBytes(&val, sizeof(uint_8));
1613 }
1614 }
1615}
1616
1617void
1618POutPersist::PutStr(string const& str)
1619{
1620 PutRawUByte(PPS_STRING);
1621 PutRawI4(str.length());
1622 PutRawBytes(str.c_str(), str.length());
1623}
1624
1625void
1626POutPersist::PutLine(char const* ptr, size_t len)
1627{
1628 string str = ptr;
1629 PutStr(str);
1630}
1631
1632
1633void
1634POutPersist::PutObject(AnyDataObj & o)
1635{
1636 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
1637 if (!f)
1638 throw NotFoundExc("PInPersist::PutObject() class not registered");
1639 PPersist* ppo = f();
1640 ppo->SetDataObj(o);
1641 PutPPObject(ppo);
1642}
1643
1644void
1645POutPersist::PutObject(AnyDataObj & o, string tagname)
1646{
1647 WriteTag(tagname);
1648 PutObject(o);
1649}
1650
1651
1652void
1653POutPersist::PutPPObject(PPersist const* obj)
1654{
1655 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
1656
1657 // We have to write the object
1658 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
1659 PutRawUByte(PPS_OBJECT); // We write the Object Tag
1660 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
1661 PutRawU8(oid); // Write the PPS Object Id
1662 obj->WriteSelf(*this);
1663 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1664 PutRawU8(oid); // and again its PPS Object Id
1665}
1666
1667bool
1668POutPersist::serializeNullAndRepeat(PPersist const* x)
1669{
1670 if (x == NULL) {
1671 PutRawUByte(PPS_NULL);
1672 return true;
1673 }
1674
1675 int_8 pos;
1676 uint_8 id = findObjectId(x, pos);
1677 if (id > 0) {
1678 PutRawUByte(PPS_REFERENCE);
1679 PutRawU8(id); // Writing the corresponding object Id
1680 PutRawI8(pos); // The original object position
1681 return true;
1682 }
1683
1684 return false; // Object have to be written in stream ...
1685}
1686
1687uint_8
1688POutPersist::assignObjectId(PPersist const* x)
1689{
1690 pps_OId += 16; // We keep the three first bytes for future usage
1691 // Bit 1 non zero -> Object can be referenced
1692 uint_8 id = pps_OId;
1693 uint_8 mid = x->getMemOId();
1694 if (mid > 0) {
1695 int_8 pos;
1696 if (findObjectId(x,pos) > 0)
1697 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
1698 id += 1; // Bit 1 non zero -> Object can be referenced
1699 objreftag rt;
1700 rt.ppsoid = id;
1701#ifdef STREAMPOS_IS_CLASS
1702 rt.ppspos = s->tellp().offset();
1703#else
1704 rt.ppspos = s->tellp();
1705#endif
1706 objList[mid] = rt;
1707 }
1708 return id;
1709}
1710
1711uint_8
1712POutPersist::findObjectId(PPersist const* x, int_8 & pos)
1713{
1714 pos = -1;
1715 uint_8 mid = x->getMemOId();
1716 if (mid == 0) return(0);
1717 ObjList::iterator i = objList.find(mid);
1718 if (i == objList.end()) return 0;
1719 pos = (*i).second.ppspos;
1720 return (*i).second.ppsoid;
1721}
1722
1723
Note: See TracBrowser for help on using the repository browser.