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

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

Contournement du Pb ifstream::seekg(ios::end) pour Linux-g++ ds ppersist.cc , Reza 11/07/2000

File size: 40.9 KB
RevLine 
[241]1#include "machdefs.h"
[251]2#include <stdio.h>
3#include <sys/types.h>
4#include <time.h>
[241]5#include "pexceptions.h"
[219]6#include "ppersist.h"
[802]7#include "anydataobj.h"
[219]8#include <fstream.h>
[661]9#include <iostream.h>
[241]10#include <typeinfo>
[219]11
12
13#ifdef __mac__
14#include "unixmac.h"
15#include <SIOUX.h>
16#endif
17
[802]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
[241]25#define MAXTAGLEN 255
26
[219]27//++
[241]28// Class PIOPersist
[219]29// Lib Outils++
30// include ppersist.h
31//
[241]32// Root class for persistant files. Handles the registration of
33// persistant classes
[219]34//--
35
36//++
[241]37// Links See
[219]38// PPersist
[241]39// PInPersist
40// POutPersist
[219]41//--
42
43
[742]44MD5_CONTEXT PIOPersist::ctx;
[802]45PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
46map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
47map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
[241]48
[269]49//++
50void
51PIOPersist::Initialize()
52// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
53//--
54{
[802]55ppclassList = new PIOPersist::ClassList;
56ppclassNameList = new map<string, uint_8>;
57dobjclassNameList = new map<string, uint_8>;
[269]58}
[241]59
[219]60//++
61void
[802]62PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
[219]63//
[802]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
[219]68//
69//--
70{
[802]71 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
72 cerr << "RegisterClass : Error, " << hex << classId << dec
73 << " already registered." << endl;
[816]74 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
[802]75 }
76 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
77 cerr << "RegisterClass : Error (2) " << ppclass_name
78 << " already registered." << endl;
[816]79 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
[219]80 }
81
[802]82 (*ppclassList)[classId] = f;
83 (*ppclassNameList)[ppclass_name] = classId;
[219]84}
85
[802]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{
[816]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 }
[219]103
[802]104 (*dobjclassNameList)[class_name] = classId;
105}
106
107// class_typename should be typeid(DataObject).name(), to be
108// used by POutPersist::PutDataObject() methods.
109
[241]110PIOPersist::ClassCreatorFunc
111PIOPersist::FindCreatorFunc(uint_8 classId)
[802]112// Returns the PPersist class creator function for the specified classId
[219]113{
[802]114 ClassList::iterator i = ppclassList->find(classId);
115 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
[241]116 return (*i).second;
[219]117}
118
[802]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;
[219]126
[802]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
[219]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//++
[241]203// Links See
[219]204// PInPersist
205// POutPersist
[241]206// PIOPersist
[219]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{
[802]240 s.PutPPObject(this);
[219]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
[241]250// objet, utiliser PInPersist::ReadObject.
251// Il faut qu'on soit un objet ecrit
[219]252//--
253{
[241]254 // We should be the exact type
255 // Check tag value
[802]256 unsigned char ppstype,ppstag;
[588]257 s.GetTypeTag(ppstype);
[802]258 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
[241]259 }
[802]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)
[241]277 }
[802]278 else if ( ppstype == PInPersist::PPS_REFERENCE )
279 s.ReadReference(*this);
[219]280
[802]281 else throw FileFormatExc("PPersist::Read() : not an object in flow");
282
[219]283}
284
285//++
[241]286void
287PPersist::Write(POutPersist& s, string const& tag) const
[219]288//
[241]289// Ecrit l'objet dans le fichier PPersist avec un tag
[219]290//--
291{
[241]292 s.WriteTag(tag);
[802]293 s.PutPPObject(this);
[219]294}
295
296//++
297void
[241]298PPersist::ReadAtTag(PInPersist& s, string const& tag)
[219]299//
300// Lit l'objet à la position du tag numéro "tagid".
301//--
302{
[241]303 if (!s.GotoTag(tag))
304 throw NotFoundExc("PPersist::ReadAtTag tag not found");
305 Read(s);
[219]306}
307
[802]308// Renvoie l'identificateur de l'objet - par defaut=0
[219]309
[802]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
[219]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{
[241]357 s = new ifstream(flnm.c_str(),ios::in | IOS_BIN);
358
359 // Read and check header
360
[219]361 char rbuf[36];
[241]362 GetRawBytes(rbuf, 32);
[576]363 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
[241]364 throw FileFormatExc("PInPersist::PInPersist bad header");
[219]365 }
[802]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 }
[241]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;
[802]387 #ifndef __MWERKS__
[742]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
[241]395 creationdate = mktime(&tm);
[802]396 filename = flnm; // keep the filename
397 seqread = true; // To flag non sequential reads
[241]398 if (scan) Scan();
[219]399}
400
401
402
403PInPersist::~PInPersist()
404{
[802]405 ObjList::iterator i;
406 for(i=objList.begin(); i!= objList.end(); i++)
407 if ((*i).second) delete (*i).second;
[219]408 delete s;
409}
410
411
[802]412string
413PInPersist::CreationDateStr()
414{
415 time_t cdt = CreationDate();
416 string cdate = ctime(&cdt);
417 return(cdate);
418}
419
[219]420void
421PInPersist::Scan()
422{
[241]423 // On cherche la liste des tags, a la fin du fichier
[219]424
[802]425 unsigned char ppstype;
[241]426 size_t debut;
427#ifdef STREAMPOS_IS_CLASS
[219]428 debut = s->tellg().offset();
[241]429#else
[219]430 debut = s->tellg();
[241]431#endif
[219]432
[241]433 // Find tag entries at end of file
[1063]434#if !defined(Linux)
[241]435 s->seekg(-(sizeof(int_8)+1), ios::end);
[1063]436#else
437 // There seems to be a bug where seekg with ios::end under Linux
438 // So, we use seek with ios::beg
439 s->seekg(0, ios::end);
440 int_8 tagpos = s->tellg() - (sizeof(int_8)+1);
441 s->seekg(tagpos, ios::beg);
442#endif
443
[588]444 GetTypeTag(ppstype);
[241]445 if (ppstype != PPS_EOF)
446 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
[219]447
[241]448 int_8 pos;
449 GetRawI8(pos);
450 if (pos < 0) { // no tags
451 s->seekg(debut);
452 return;
453 }
[219]454
[241]455 char buffer[MAXTAGLEN+1];
456 s->seekg(pos);
457 while (true) {
[588]458 GetTypeTag(ppstype);
[241]459 if (ppstype == PPS_EOF) break;
460
461 if (ppstype != PPS_TAG)
462 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
[219]463
[241]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';
[219]471
[241]472 tags[buffer] = pos;
[219]473 }
[241]474 s->seekg(debut);
[219]475}
476
477
[256]478int
479PInPersist::NbTags()
480{
481 return tags.size();
482}
483
[219]484bool
[241]485PInPersist::GotoTag(string const& name)
[219]486{
[241]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);
[802]492 seqread = false;
493 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[219]494 return(true);
495}
496
[256]497bool
498PInPersist::GotoTagNum(int itag)
499{
[582]500 if (itag<0 || itag >= (int)tags.size()) return false;
[256]501 map<string, int_8>::iterator i = tags.begin();
502 for (int j=0; j<itag; j++) i++;
503 s->seekg((*i).second);
[871]504 seqread = false;
[802]505 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[256]506 return(true);
507}
508
[582]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}
[256]517
[802]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
[582]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
[219]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
[588]596void
[802]597PInPersist::GetTypeTag(unsigned char& c)
[588]598{
[802]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 // }
[588]605}
[241]606
[588]607
[219]608void
[241]609PInPersist::GetRawByte(char& c)
610{
611 GetRawBytes(&c, 1);
612}
613
614void
[802]615PInPersist::GetRawUByte(unsigned char& c)
616{
617 GetRawBytes(&c, 1);
618}
619
620void
[241]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
[802]659PInPersist::CheckTag(short datasz, short datatype)
660// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]661{
[802]662 unsigned char ppstype;
[588]663 GetTypeTag(ppstype);
[802]664 if (ppstype != PPS_SIMPLE + datasz + datatype)
[256]665 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]666}
667
668void
[802]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
[241]671{
[802]672 unsigned char ppstype;
[588]673 GetTypeTag(ppstype);
[241]674 size_t filesz;
[802]675 if (sz <= 0x7fffffff) {
676 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
677 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]678 int_4 ff;
679 GetRawI4(ff); filesz=ff;
680 } else {
[802]681 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
682 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]683 uint_8 ff;
684 GetRawU8(ff); filesz=ff;
685 }
686 if (filesz != sz)
[802]687 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
[241]688}
689
690void
691PInPersist::GetByte(char& c)
692{
[802]693 CheckTag(1,PPS_DATATYPE_CHAR);
[241]694 GetRawBytes(&c, 1);
695}
696
[802]697
[241]698void
699PInPersist::GetBytes(void* ptr, size_t bytes)
700{
[802]701 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]702 GetRawBytes(ptr, bytes);
703}
704void
[219]705PInPersist::GetR4 (r_4& result)
706{
[802]707 CheckTag(4,PPS_DATATYPE_FLOAT);
[241]708 GetRawBytes(&result, sizeof(r_4));
[219]709 if (bigEndian != IS_BIG_ENDIAN)
710 bswap4(&result);
711}
712
713
714void
715PInPersist::GetR4s (r_4* tab, size_t n)
716{
[802]717 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
[241]718 GetRawBytes(tab, n*sizeof(r_4));
[219]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{
[802]730 CheckTag(8,PPS_DATATYPE_FLOAT);
[241]731 GetRawBytes(&result, sizeof(r_8));
[219]732 if (bigEndian != IS_BIG_ENDIAN)
733 bswap8(&result);
734}
735
736void
737PInPersist::GetR8s (r_8* tab, size_t n)
738{
[802]739 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
[241]740 GetRawBytes(tab, n*sizeof(r_8));
[219]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{
[802]752 CheckTag(2,PPS_DATATYPE_INTEGER);
[241]753 GetRawBytes(&result, sizeof(int_2));
[219]754 if (bigEndian != IS_BIG_ENDIAN)
755 bswap2(&result);
756}
757
758void
759PInPersist::GetI2s (int_2* tab, size_t n)
760{
[802]761 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
[241]762 GetRawBytes(tab, n*sizeof(int_2));
[219]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{
[802]774 CheckTag(2,PPS_DATATYPE_UNSIGNED);
[241]775 GetRawBytes(&result, sizeof(uint_2));
[219]776 if (bigEndian != IS_BIG_ENDIAN)
777 bswap2(&result);
778}
779
780void
781PInPersist::GetU2s (uint_2* tab, size_t n)
782{
[802]783 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
[241]784 GetRawBytes(tab, n*sizeof(uint_2));
[219]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{
[802]796 CheckTag(4,PPS_DATATYPE_INTEGER);
[241]797 GetRawBytes(&result, sizeof(int_4));
[219]798 if (bigEndian != IS_BIG_ENDIAN)
799 bswap4(&result);
800}
801
802void
803PInPersist::GetI4s (int_4* tab, size_t n)
804{
[802]805 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
[241]806 GetRawBytes(tab, n*sizeof(int_4));
[219]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{
[802]818 CheckTag(4,PPS_DATATYPE_UNSIGNED);
[241]819 GetRawBytes(&result, sizeof(uint_4));
[219]820 if (bigEndian != IS_BIG_ENDIAN)
821 bswap4(&result);
822}
823
824void
825PInPersist::GetU4s (uint_4* tab, size_t n)
826{
[802]827 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
[241]828 GetRawBytes(tab, n*sizeof(uint_4));
[219]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{
[802]841 CheckTag(8,PPS_DATATYPE_INTEGER);
[241]842 GetRawBytes(&result, sizeof(int_8));
[219]843 if (bigEndian != IS_BIG_ENDIAN)
844 bswap8(&result);
845}
846
847void
848PInPersist::GetI8s (int_8* tab, size_t n)
849{
[802]850 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
[241]851 GetRawBytes(tab, n*sizeof(int_8));
[219]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{
[802]863 CheckTag(8,PPS_DATATYPE_UNSIGNED);
[241]864 GetRawBytes(&result, sizeof(uint_8));
[219]865 if (bigEndian != IS_BIG_ENDIAN)
866 bswap8(&result);
867}
868
869void
870PInPersist::GetU8s (uint_8* tab, size_t n)
871{
[802]872 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
[241]873 GetRawBytes(tab, n*sizeof(uint_8));
[219]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{
[802]886 string str;
887 GetStr(str);
888 strncpy(ptr, str.c_str(), len);
889 ptr[len] = '\0';
[219]890}
891
[241]892void
893PInPersist::GetStr(string& str)
894{
[802]895 unsigned char ppstype;
[588]896 GetTypeTag(ppstype);
[241]897 if (ppstype != PPS_STRING)
[802]898 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
899 int_4 len;
900 GetRawI4(len);
[582]901 char * buff = new char[len+1];
[241]902 GetRawBytes(buff, len);
903 buff[len] = '\0';
904 str = buff;
905 delete[] buff;
906}
[219]907
[802]908
[241]909PPersist*
910PInPersist::ReadObject()
911{
[802]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{
[241]933 // Get tag
[802]934 unsigned char ppstype;
[588]935 GetTypeTag(ppstype);
[241]936 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]937 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]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);
[802]946 uint_8 oid,oid2;
947 GetRawU8(oid);
[241]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();
[802]957 // If a DataObject was specified , we assign it to the PPersistObject
958 if (po != NULL) object->SetDataObj(*po);
959
[241]960 object->ReadSelf(*this);
[802]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);
[241]971 return object;
[802]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 }
[241]1088 }
[802]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 }
[241]1123 }
[802]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;
[241]1130}
1131
[802]1132void
1133PInPersist::ReadReference(PPersist & ppo)
[241]1134{
[802]1135 PPersist * pr = ReadReference();
1136 ppo.ShareDataReference(*pr);
[241]1137}
1138
[802]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
[219]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
[802]1217 // PPS (POutPersist stream) Object Id initialisation
1218 pps_OId = 0;
[241]1219 // Output stream creation
1220 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
1221
1222 // Header
[802]1223 PutRawBytes("SOS-SOPHYA-PPersistFile V2 ",32);
[241]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];
[742]1231 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
[241]1232 for(int i=l; i<32; i++) datestring[i] = ' ';
1233 datestring[32] = '\0';
1234 PutRawBytes(datestring, 32);
[802]1235 filename = flnm;
[219]1236}
1237
1238POutPersist::~POutPersist()
1239{
[241]1240 if (tags.size() == 0) {
[802]1241 PutRawUByte(PPS_EOF);
[241]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;
[802]1253 PutRawUByte(PPS_TAG); // This is a tag
[241]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 }
[802]1258 PutRawUByte(PPS_EOF);
[241]1259 PutRawI8(tagPos);
1260 }
1261
1262 delete s; // Close the stream
[219]1263}
1264
1265
[241]1266void
1267POutPersist::WriteTag(string const& name)
[219]1268{
[241]1269 if (name.length() > MAXTAGLEN)
1270 throw ParmError("POutPersist::WriteTag tag name too long");
[219]1271
[241]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
[219]1278 #ifdef STREAMPOS_IS_CLASS
[241]1279 tagPos = s->tellp().offset();
[219]1280 #else
[241]1281 tagPos = s->tellp();
[219]1282 #endif
[241]1283
1284 tags[name] = tagPos;
[802]1285 PutRawUByte(PPS_TAG_MARK); // This is a tag
1286 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
[219]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)
[241]1308// void POutPersist::PutStr (string const&)
[219]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
[241]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
[802]1331POutPersist::PutRawUByte(unsigned char c)
1332{
1333 PutRawBytes(&c, 1);
1334}
1335
1336void
[241]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
[802]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
[241]1375{
[802]1376 if (sz <= 0x7fffffff) {
1377 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
[241]1378 PutRawI4(sz);
1379 } else {
[802]1380 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
[241]1381 PutRawU8(sz);
1382 }
1383}
1384
1385void
[219]1386POutPersist::PutByte(char c)
1387{
[802]1388 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
[241]1389 PutRawBytes(&c, 1);
[219]1390}
1391
[241]1392
1393
[219]1394void
1395POutPersist::PutBytes(void const* ptr, size_t bytes)
1396{
[802]1397 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]1398 PutRawBytes(ptr, bytes);
[219]1399}
1400
1401void
1402POutPersist::PutR4 (r_4 val)
1403{
[802]1404 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
[241]1405
[219]1406 if (bigEndian != IS_BIG_ENDIAN)
1407 bswap4(&val);
1408
[241]1409 PutRawBytes(&val, sizeof(r_4));
[219]1410}
1411
1412void
1413POutPersist::PutR4s (r_4 const* tab, size_t n)
1414{
[802]1415 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
[241]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 }
[219]1426}
1427
1428void
1429POutPersist::PutR8 (r_8 val)
1430{
[802]1431 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
[241]1432
[219]1433 if (bigEndian != IS_BIG_ENDIAN)
1434 bswap8(&val);
1435
[241]1436 PutRawBytes(&val, sizeof(r_8));
[219]1437}
1438
1439void
1440POutPersist::PutR8s (r_8 const* tab, size_t n)
1441{
[802]1442 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
[241]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 }
[219]1453}
1454
1455void
1456POutPersist::PutI2 (int_2 val)
1457{
[802]1458 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
[241]1459
[219]1460 if (bigEndian != IS_BIG_ENDIAN)
1461 bswap2(&val);
1462
[241]1463 PutRawBytes(&val, sizeof(int_2));
[219]1464}
1465
1466void
1467POutPersist::PutI2s (int_2 const* tab, size_t n)
1468{
[802]1469 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
[241]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 }
[219]1480}
1481
1482void
1483POutPersist::PutU2 (uint_2 val)
1484{
[802]1485 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
[241]1486
[219]1487 if (bigEndian != IS_BIG_ENDIAN)
1488 bswap2(&val);
1489
[241]1490 PutRawBytes(&val, sizeof(uint_2));
[219]1491}
1492
1493void
1494POutPersist::PutU2s (uint_2 const* tab, size_t n)
1495{
[802]1496 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
[241]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 }
[219]1507}
1508
1509void
1510POutPersist::PutI4 (int_4 val)
1511{
[802]1512 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
[241]1513
[219]1514 if (bigEndian != IS_BIG_ENDIAN)
1515 bswap4(&val);
1516
[241]1517 PutRawBytes(&val, sizeof(int_4));
[219]1518}
1519
1520void
1521POutPersist::PutI4s (int_4 const* tab, size_t n)
1522{
[802]1523 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
[241]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 }
[219]1534}
1535
1536void
1537POutPersist::PutU4 (uint_4 val)
1538{
[802]1539 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
[241]1540
[219]1541 if (bigEndian != IS_BIG_ENDIAN)
1542 bswap4(&val);
1543
[241]1544 PutRawBytes(&val, sizeof(uint_4));
[219]1545}
1546
1547void
1548POutPersist::PutU4s (uint_4 const* tab, size_t n)
1549{
[802]1550 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
[241]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 }
[219]1561}
1562
1563void
1564POutPersist::PutI8 (int_8 val)
1565{
[802]1566 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
[241]1567
[219]1568 if (bigEndian != IS_BIG_ENDIAN)
1569 bswap8(&val);
1570
[241]1571 PutRawBytes(&val, sizeof(int_8));
[219]1572}
1573
1574void
1575POutPersist::PutI8s (int_8 const* tab, size_t n)
1576{
[802]1577 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
[241]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 }
[219]1588}
1589
1590void
1591POutPersist::PutU8 (uint_8 val)
1592{
[802]1593 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
[241]1594
[219]1595 if (bigEndian != IS_BIG_ENDIAN)
1596 bswap8(&val);
1597
[241]1598 PutRawBytes(&val, sizeof(uint_8));
[219]1599}
1600
1601void
1602POutPersist::PutU8s (uint_8 const* tab, size_t n)
1603{
[802]1604 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
[241]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 }
[219]1615}
1616
1617void
[241]1618POutPersist::PutStr(string const& str)
1619{
[802]1620 PutRawUByte(PPS_STRING);
1621 PutRawI4(str.length());
[241]1622 PutRawBytes(str.c_str(), str.length());
1623}
1624
1625void
[219]1626POutPersist::PutLine(char const* ptr, size_t len)
1627{
[802]1628 string str = ptr;
1629 PutStr(str);
1630}
[241]1631
[802]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);
[219]1642}
1643
[241]1644void
[802]1645POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]1646{
[802]1647 WriteTag(tagname);
1648 PutObject(o);
1649}
[219]1650
[802]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
[241]1662 obj->WriteSelf(*this);
[802]1663 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1664 PutRawU8(oid); // and again its PPS Object Id
[241]1665}
[219]1666
[241]1667bool
1668POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1669{
[241]1670 if (x == NULL) {
[802]1671 PutRawUByte(PPS_NULL);
[241]1672 return true;
1673 }
[219]1674
[802]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
[241]1681 return true;
1682 }
[219]1683
[802]1684 return false; // Object have to be written in stream ...
[219]1685}
1686
[802]1687uint_8
[241]1688POutPersist::assignObjectId(PPersist const* x)
[219]1689{
[802]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 ! ");
[821]1698 id += 1; // Bit 1 non zero -> Object can be referenced
[802]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 }
[241]1708 return id;
[219]1709}
1710
[802]1711uint_8
1712POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]1713{
[802]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;
[219]1721}
1722
[241]1723
Note: See TracBrowser for help on using the repository browser.