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

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

Correction bug ds ppersist.cc - Reza 10/4/2000

File size: 40.6 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
434 s->seekg(-(sizeof(int_8)+1), ios::end);
[588]435 GetTypeTag(ppstype);
[241]436 if (ppstype != PPS_EOF)
437 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
[219]438
[241]439 int_8 pos;
440 GetRawI8(pos);
441 if (pos < 0) { // no tags
442 s->seekg(debut);
443 return;
444 }
[219]445
[241]446 char buffer[MAXTAGLEN+1];
447 s->seekg(pos);
448 while (true) {
[588]449 GetTypeTag(ppstype);
[241]450 if (ppstype == PPS_EOF) break;
451
452 if (ppstype != PPS_TAG)
453 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
[219]454
[241]455 GetRawI8(pos);
456 int_4 len;
457 GetRawI4(len);
458 if (len > MAXTAGLEN)
459 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
460 GetRawBytes(buffer, len);
461 buffer[len] = '\0';
[219]462
[241]463 tags[buffer] = pos;
[219]464 }
[241]465 s->seekg(debut);
[219]466}
467
468
[256]469int
470PInPersist::NbTags()
471{
472 return tags.size();
473}
474
[219]475bool
[241]476PInPersist::GotoTag(string const& name)
[219]477{
[241]478 map<string, int_8>::iterator i = tags.find(name);
479 if (i == tags.end())
480 return false;
481 // throw NotFoundExc("PInPersist::GotoTag tag not found");
482 s->seekg((*i).second);
[802]483 seqread = false;
484 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[219]485 return(true);
486}
487
[256]488bool
489PInPersist::GotoTagNum(int itag)
490{
[582]491 if (itag<0 || itag >= (int)tags.size()) return false;
[256]492 map<string, int_8>::iterator i = tags.begin();
493 for (int j=0; j<itag; j++) i++;
494 s->seekg((*i).second);
[871]495 seqread = false;
[802]496 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
[256]497 return(true);
498}
499
[582]500string
501PInPersist::GetTagName(int itag)
502{
503 if (itag<0 || itag >= (int)tags.size()) return "";
504 map<string, int_8>::iterator i = tags.begin();
505 for (int j=0; j<itag; j++) i++;
506 return((*i).first);
507}
[256]508
[802]509string
510PInPersist::GetTagClassName(int itag)
511{
512 // A faire
513// if (itag<0 || itag >= (int)tags.size()) return "";
514// map<string, int_8>::iterator i = tags.begin();
515// for (int j=0; j<itag; j++) i++;
516// uint_8 cid = (*i).second;
517// return(GetClassName(cid));
518 return("");
519}
520
[582]521static vector<string> * ret_tag_names = NULL;
522vector<string> const &
523PInPersist::GetTagNames()
524{
525if (ret_tag_names) delete ret_tag_names;
526ret_tag_names = new vector<string> ;
527map<string, int_8>::iterator i;
528for(i=tags.begin(); i!=tags.end(); i++) ret_tag_names->push_back((*i).first);
529return(*ret_tag_names);
530}
531
[219]532//++
533// void PInPersist::GetByte(char& c)
534// void PInPersist::GetBytes(void* ptr, size_t bytes)
535// void PInPersist::GetR4 (r_4& result)
536// void PInPersist::GetR4s (r_4* tab, size_t n)
537// void PInPersist::GetR8 (r_8& result)
538// void PInPersist::GetR8s (r_8* tab, size_t n)
539// void PInPersist::GetI2 (int_2& result)
540// void PInPersist::GetI2s (int_2* tab, size_t n)
541// void PInPersist::GetU2 (uint_2& result)
542// void PInPersist::GetU2s (uint_2* tab, size_t n)
543// void PInPersist::GetI4 (int_4& result)
544// void PInPersist::GetI4s (int_4* tab, size_t n)
545// void PInPersist::GetU4 (uint_4& result)
546// void PInPersist::GetU4s (uint_4* tab, size_t n)
547// void PInPersist::GetI8 (int_8& result)
548// void PInPersist::GetI8s (int_8* tab, size_t n)
549// void PInPersist::GetU8 (uint_8& result)
550// void PInPersist::GetU8s (uint_8* tab, size_t n)
551// Lecture de données portables depuis le fichier PPersist. Pour chaque type
552// de données, on peut lire une valeur, ou un tableau de valeurs.
553// void PInPersist::GetLine(char* ptr, size_t len)
554// Lecture d'une ligne de texte depuis le fichier PPersist.
555//--
556
557
558static inline void bswap8(void* p)
559{
560 uint_8 tmp = *(uint_8*)p;
561 *(uint_8*)p = ((tmp >> (7*8)) & 0x000000FF) |
562 ((tmp >> (5*8)) & 0x0000FF00) |
563 ((tmp >> (3*8)) & 0x00FF0000) |
564 ((tmp >> (1*8)) & 0xFF000000) |
565 ((tmp & 0xFF000000) << (1*8)) |
566 ((tmp & 0x00FF0000) << (3*8)) |
567 ((tmp & 0x0000FF00) << (5*8)) |
568 ((tmp & 0x000000FF) << (7*8));
569}
570
571static inline void bswap4(void* p)
572{
573 uint_4 tmp = *(uint_4*)p;
574 *(uint_4*)p = ((tmp >> 24) & 0x000000FF) |
575 ((tmp >> 8) & 0x0000FF00) |
576 ((tmp & 0x0000FF00) << 8) |
577 ((tmp & 0x000000FF) << 24);
578}
579
580static inline void bswap2(void* p)
581{
582 uint_2 tmp = *(uint_2*)p;
583 *(uint_2*)p = ((tmp >> 8) & 0x00FF) |
584 ((tmp & 0x00FF) << 8);
585}
586
[588]587void
[802]588PInPersist::GetTypeTag(unsigned char& c)
[588]589{
[802]590 c = PPS_TAG_MARK;
591 while (c == PPS_TAG_MARK) GetRawUByte(c);
592 // while (c == PPS_TAG_MARK) { Il ne faut plus faire ca !
593 // objList.clear(); $CHECK$ Reza 03/2000
594 // GetRawByte(c);
595 // }
[588]596}
[241]597
[588]598
[219]599void
[241]600PInPersist::GetRawByte(char& c)
601{
602 GetRawBytes(&c, 1);
603}
604
605void
[802]606PInPersist::GetRawUByte(unsigned char& c)
607{
608 GetRawBytes(&c, 1);
609}
610
611void
[241]612PInPersist::GetRawBytes(void* ptr, size_t bytes)
613{
614 s->read((char*)ptr, bytes);
615}
616
617void
618PInPersist::GetRawI2 (int_2& result)
619{
620 GetRawBytes(&result, sizeof(int_2));
621 if (bigEndian != IS_BIG_ENDIAN)
622 bswap2(&result);
623}
624
625void
626PInPersist::GetRawI4 (int_4& result)
627{
628 GetRawBytes(&result, sizeof(int_4));
629 if (bigEndian != IS_BIG_ENDIAN)
630 bswap4(&result);
631}
632
633void
634PInPersist::GetRawI8 (int_8& result)
635{
636 GetRawBytes(&result, sizeof(int_8));
637 if (bigEndian != IS_BIG_ENDIAN)
638 bswap8(&result);
639}
640
641void
642PInPersist::GetRawU8 (uint_8& result)
643{
644 GetRawBytes(&result, sizeof(uint_8));
645 if (bigEndian != IS_BIG_ENDIAN)
646 bswap8(&result);
647}
648
649void
[802]650PInPersist::CheckTag(short datasz, short datatype)
651// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]652{
[802]653 unsigned char ppstype;
[588]654 GetTypeTag(ppstype);
[802]655 if (ppstype != PPS_SIMPLE + datasz + datatype)
[256]656 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
[241]657}
658
659void
[802]660PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
661// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]662{
[802]663 unsigned char ppstype;
[588]664 GetTypeTag(ppstype);
[241]665 size_t filesz;
[802]666 if (sz <= 0x7fffffff) {
667 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
668 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]669 int_4 ff;
670 GetRawI4(ff); filesz=ff;
671 } else {
[802]672 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
673 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
[241]674 uint_8 ff;
675 GetRawU8(ff); filesz=ff;
676 }
677 if (filesz != sz)
[802]678 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
[241]679}
680
681void
682PInPersist::GetByte(char& c)
683{
[802]684 CheckTag(1,PPS_DATATYPE_CHAR);
[241]685 GetRawBytes(&c, 1);
686}
687
[802]688
[241]689void
690PInPersist::GetBytes(void* ptr, size_t bytes)
691{
[802]692 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]693 GetRawBytes(ptr, bytes);
694}
695void
[219]696PInPersist::GetR4 (r_4& result)
697{
[802]698 CheckTag(4,PPS_DATATYPE_FLOAT);
[241]699 GetRawBytes(&result, sizeof(r_4));
[219]700 if (bigEndian != IS_BIG_ENDIAN)
701 bswap4(&result);
702}
703
704
705void
706PInPersist::GetR4s (r_4* tab, size_t n)
707{
[802]708 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
[241]709 GetRawBytes(tab, n*sizeof(r_4));
[219]710 if (bigEndian == IS_BIG_ENDIAN) return;
711
712 for (unsigned int i=0; i<n; i++)
713 bswap4(tab+i);
714
715 return;
716}
717
718void
719PInPersist::GetR8 (r_8& result)
720{
[802]721 CheckTag(8,PPS_DATATYPE_FLOAT);
[241]722 GetRawBytes(&result, sizeof(r_8));
[219]723 if (bigEndian != IS_BIG_ENDIAN)
724 bswap8(&result);
725}
726
727void
728PInPersist::GetR8s (r_8* tab, size_t n)
729{
[802]730 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
[241]731 GetRawBytes(tab, n*sizeof(r_8));
[219]732 if (bigEndian == IS_BIG_ENDIAN) return;
733
734 for (unsigned int i=0; i<n; i++)
735 bswap8(tab+i);
736
737 return;
738}
739
740void
741PInPersist::GetI2 (int_2& result)
742{
[802]743 CheckTag(2,PPS_DATATYPE_INTEGER);
[241]744 GetRawBytes(&result, sizeof(int_2));
[219]745 if (bigEndian != IS_BIG_ENDIAN)
746 bswap2(&result);
747}
748
749void
750PInPersist::GetI2s (int_2* tab, size_t n)
751{
[802]752 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
[241]753 GetRawBytes(tab, n*sizeof(int_2));
[219]754 if (bigEndian == IS_BIG_ENDIAN) return;
755
756 for (unsigned int i=0; i<n; i++)
757 bswap2(tab+i);
758
759 return;
760}
761
762void
763PInPersist::GetU2 (uint_2& result)
764{
[802]765 CheckTag(2,PPS_DATATYPE_UNSIGNED);
[241]766 GetRawBytes(&result, sizeof(uint_2));
[219]767 if (bigEndian != IS_BIG_ENDIAN)
768 bswap2(&result);
769}
770
771void
772PInPersist::GetU2s (uint_2* tab, size_t n)
773{
[802]774 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
[241]775 GetRawBytes(tab, n*sizeof(uint_2));
[219]776 if (bigEndian == IS_BIG_ENDIAN) return;
777
778 for (unsigned int i=0; i<n; i++)
779 bswap2(tab+i);
780
781 return;
782}
783
784void
785PInPersist::GetI4 (int_4& result)
786{
[802]787 CheckTag(4,PPS_DATATYPE_INTEGER);
[241]788 GetRawBytes(&result, sizeof(int_4));
[219]789 if (bigEndian != IS_BIG_ENDIAN)
790 bswap4(&result);
791}
792
793void
794PInPersist::GetI4s (int_4* tab, size_t n)
795{
[802]796 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
[241]797 GetRawBytes(tab, n*sizeof(int_4));
[219]798 if (bigEndian == IS_BIG_ENDIAN) return;
799
800 for (unsigned int i=0; i<n; i++)
801 bswap4(tab+i);
802
803 return;
804}
805
806void
807PInPersist::GetU4 (uint_4& result)
808{
[802]809 CheckTag(4,PPS_DATATYPE_UNSIGNED);
[241]810 GetRawBytes(&result, sizeof(uint_4));
[219]811 if (bigEndian != IS_BIG_ENDIAN)
812 bswap4(&result);
813}
814
815void
816PInPersist::GetU4s (uint_4* tab, size_t n)
817{
[802]818 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
[241]819 GetRawBytes(tab, n*sizeof(uint_4));
[219]820 if (bigEndian == IS_BIG_ENDIAN) return;
821
822 for (unsigned int i=0; i<n; i++)
823 bswap4(tab+i);
824
825 return;
826}
827
828
829void
830PInPersist::GetI8 (int_8& result)
831{
[802]832 CheckTag(8,PPS_DATATYPE_INTEGER);
[241]833 GetRawBytes(&result, sizeof(int_8));
[219]834 if (bigEndian != IS_BIG_ENDIAN)
835 bswap8(&result);
836}
837
838void
839PInPersist::GetI8s (int_8* tab, size_t n)
840{
[802]841 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
[241]842 GetRawBytes(tab, n*sizeof(int_8));
[219]843 if (bigEndian == IS_BIG_ENDIAN) return;
844
845 for (unsigned int i=0; i<n; i++)
846 bswap8(tab+i);
847
848 return;
849}
850
851void
852PInPersist::GetU8 (uint_8& result)
853{
[802]854 CheckTag(8,PPS_DATATYPE_UNSIGNED);
[241]855 GetRawBytes(&result, sizeof(uint_8));
[219]856 if (bigEndian != IS_BIG_ENDIAN)
857 bswap8(&result);
858}
859
860void
861PInPersist::GetU8s (uint_8* tab, size_t n)
862{
[802]863 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
[241]864 GetRawBytes(tab, n*sizeof(uint_8));
[219]865 if (bigEndian == IS_BIG_ENDIAN) return;
866
867 for (unsigned int i=0; i<n; i++)
868 bswap8(tab+i);
869
870 return;
871}
872
873
874void
875PInPersist::GetLine(char* ptr, size_t len)
876{
[802]877 string str;
878 GetStr(str);
879 strncpy(ptr, str.c_str(), len);
880 ptr[len] = '\0';
[219]881}
882
[241]883void
884PInPersist::GetStr(string& str)
885{
[802]886 unsigned char ppstype;
[588]887 GetTypeTag(ppstype);
[241]888 if (ppstype != PPS_STRING)
[802]889 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
890 int_4 len;
891 GetRawI4(len);
[582]892 char * buff = new char[len+1];
[241]893 GetRawBytes(buff, len);
894 buff[len] = '\0';
895 str = buff;
896 delete[] buff;
897}
[219]898
[802]899
[241]900PPersist*
901PInPersist::ReadObject()
902{
[802]903 return(GetPPObject());
904}
905
906void
907PInPersist::GetObject(AnyDataObj & o)
908{
909 GetPPObject(&o);
910 return;
911}
912
913void
914PInPersist::GetObject(AnyDataObj & o, string tagname)
915{
916 GotoTag(tagname);
917 GetPPObject(&o);
918 return;
919}
920
921PPersist*
922PInPersist::GetPPObject(AnyDataObj * po)
923{
[241]924 // Get tag
[802]925 unsigned char ppstype;
[588]926 GetTypeTag(ppstype);
[241]927 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
[256]928 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
[241]929 }
930
931 if (ppstype == PPS_NULL) {
932 return NULL;
933 } else if (ppstype == PPS_OBJECT) {
934 // Get class id
935 uint_8 classId;
936 GetRawU8(classId);
[802]937 uint_8 oid,oid2;
938 GetRawU8(oid);
[241]939
940 // Get factory method
941 ClassCreatorFunc f = FindCreatorFunc(classId);
942 if (!f) {
943 throw NotFoundExc("PInPersist::ReadObject class not registered");
944 }
945
946 // Create object
947 PPersist* object = f();
[802]948 // If a DataObject was specified , we assign it to the PPersistObject
949 if (po != NULL) object->SetDataObj(*po);
950
[241]951 object->ReadSelf(*this);
[802]952 unsigned char ppstag;
953 // Read the ENDOBJECT
954 GetRawUByte(ppstag);
955 if (ppstag != PPS_ENDOBJECT)
956 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
957 GetRawU8(oid2);
958 if (oid2 != oid)
959 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
960
961 KeepOId(oid, *object);
[241]962 return object;
[802]963 }
964 else if (ppstype == PPS_REFERENCE)
965 return ReadReference();
966
967 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
968}
969
970
971void
972PInPersist::AnalyseTags(int lev)
973{
974 unsigned char ppstag=0;
975 unsigned char ppst1,ppst2,ppst3;
976 uint_8 cpos,fsize;
977 uint_8 ui8,cid,oid;
978 int_4 i4;
979 int_8 i8;
980 char * buff;
981 string str;
982
983 cout << "\n ---------------------------------------------------------- " << endl;
984 cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl;
985
986
987#ifdef STREAMPOS_IS_CLASS
988 cpos = s->tellg().offset();
989#else
990 cpos = s->tellg();
991#endif
992 s->seekg(0,ios::end);
993#ifdef STREAMPOS_IS_CLASS
994 fsize = s->tellg().offset();
995#else
996 fsize = s->tellg();
997#endif
998 s->seekg(cpos,ios::beg);
999
1000 cout << " Version= " << Version() << " FileSize= " << fsize
1001 << " Creation Date= " << CreationDateStr() << endl;
1002
1003 uint_8 totntags = 0;
1004 bool eofok = false;
1005
1006 while ( (ppstag != PPS_EOF) && (cpos < fsize) ) {
1007#ifdef STREAMPOS_IS_CLASS
1008 cpos = s->tellg().offset();
1009#else
1010 cpos = s->tellg();
1011#endif
1012 GetRawUByte(ppstag);
1013 totntags++;
1014
1015 ppst1 = ppstag&0x0f; // bits 0123
1016 ppst2 = ppstag&0x30; // bits 45
1017 ppst3 = ppstag&0xc0; // bits 67
1018 if ((ppst2 == 0) && (ppst3 == 0) ) {
1019 switch (ppst1) {
1020
1021 case PPS_NULL :
1022 if (lev > 1) cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
1023 break;
1024
1025 case PPS_STRING :
1026 GetRawI4(i4);
1027 if (lev > 1) cout << "<PPS_STRING> tag at position " << hex << cpos << dec
1028 << " Length=" << i4 << endl;
1029 s->seekg(i4,ios::cur);
1030 break;
1031
1032 case PPS_OBJECT :
1033 GetRawU8(cid);
1034 GetRawU8(oid);
1035 cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid
1036 << " ObjectId= " << oid << dec << endl;
1037 break;
1038
1039 case PPS_REFERENCE :
1040 GetRawU8(oid);
1041 GetRawI8(i8);
1042 cout << "<PPS_REFERENCE> tag at position " << hex << cpos << " ObjectId= "
1043 << oid << " OrigPos=" << i8 << dec << endl;
1044 break;
1045
1046 case PPS_TAG_MARK :
1047 cout << "<PPS_TAG_MARK> tag at position " << hex << cpos << dec << endl;
1048 break;
1049
1050 case PPS_ENDOBJECT :
1051 GetRawU8(oid);
1052 cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << " ObjectId= "
1053 << oid << dec << endl;
1054 break;
1055
1056 case PPS_TAG :
1057 GetRawI8(i8);
1058 GetRawI4(i4);
1059 buff = new char[i4+1];
1060 GetRawBytes(buff, i4);
1061 buff[i4] = '\0'; str = buff;
1062 delete[] buff;
1063 cout << "<PPS_TAG> tag at position " << hex << cpos << dec
1064 << " Name= " << str << endl;
1065 break;
1066
1067 case PPS_EOF :
1068 GetRawI8(i8);
1069 cout << "<PPS_EOF> tag at position " << hex << cpos
1070 << " TagPos=" << i8 << dec << endl;
1071 eofok = true;
1072 break;
1073
1074 default :
1075 cerr << " ERROR : Unexpected tag value " << hex << ppstag
1076 << " At position" << cpos << dec << endl;
1077 throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
1078 }
[241]1079 }
[802]1080 else {
1081 string dtype = "???? x";
1082 if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
1083 else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
1084 else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
1085 else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
1086 int_4 dsize = ppst1;
1087 char sb[16];
1088 sprintf(sb, "%d", dsize);
1089 dtype += sb;
1090
1091 switch (ppst2) {
1092
1093 case PPS_SIMPLE :
1094 if (lev > 2) cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec
1095 << " DataType=" << dtype << endl;
1096 s->seekg(dsize, ios::cur);
1097 break;
1098
1099 case PPS_SIMPLE_ARRAY4 :
1100 GetRawI4(i4);
1101 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec
1102 << " DataType=" << dtype << " NElts= " << i4 << endl;
1103 s->seekg((uint_8)dsize*(uint_8)i4, ios::cur);
1104 break;
1105
1106 case PPS_SIMPLE_ARRAY8 :
1107 GetRawU8(ui8);
1108 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec
1109 << " DataType=" << dtype << " NElts= " << ui8 << endl;
1110 s->seekg((uint_8)dsize*ui8, ios::cur);
1111 break;
1112 }
1113 }
[241]1114 }
[802]1115 if (!eofok)
1116 throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
1117
1118 cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl;
1119 cout << " ---------------------------------------------------------- \n" << endl;
1120 return;
[241]1121}
1122
[802]1123void
1124PInPersist::ReadReference(PPersist & ppo)
[241]1125{
[802]1126 PPersist * pr = ReadReference();
1127 ppo.ShareDataReference(*pr);
[241]1128}
1129
[802]1130
1131PPersist *
1132PInPersist::ReadReference()
1133{
1134 uint_8 oid;
1135 int_8 pos;
1136 GetRawU8(oid);
1137 GetRawI8(pos);
1138 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
1139 map<uint_8, PPersist *>::iterator i = objList.find(oid);
1140 if (i != objList.end()) return (*i).second;
1141 else { // We may have skeeped it !
1142 // Let's try to read it
1143 int_8 cpos;
1144#ifdef STREAMPOS_IS_CLASS
1145 cpos = s->tellg().offset();
1146#else
1147 cpos = s->tellg();
1148#endif
1149 s->seekg(pos);
1150 PPersist* ppo = ReadObject();
1151 s->seekg(cpos);
1152 delete ppo;
1153 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
1154
1155 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
1156 if (i2 == objList.end())
1157 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
1158 return (*i2).second;
1159 }
1160}
1161
1162
1163void
1164PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
1165{
1166 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
1167 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
1168 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
1169 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoTag)
1170 // et pas avec une lecture sequentielle ... Reza 03/2000
1171 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
1172 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
1173 PPersist *pp = (*objList.find(oid)).second;
1174 ppo.ShareDataReference(*pp);
1175 }
1176 else {
1177 PPersist * npp = ppo.CloneSharedReference();
1178 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
1179 objList[oid] = npp;
1180 }
1181 return;
1182}
1183
[219]1184//++
1185// Class POutPersist
1186// Lib Outils++
1187// include ppersist.h
1188//
1189// Fichier d'objets persistants, en écriture.
1190//--
1191
1192
1193//++
1194// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
1195//
1196// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
1197// sur machines petit-boutiennes, et gros-boutien sur machines
1198// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
1199// ou PPersist::PPS_BIG_ENDIAN.
1200//--
1201POutPersist::POutPersist(string const& flnm, int endianness)
1202{
1203 if (endianness == -1)
1204 bigEndian = IS_BIG_ENDIAN;
1205 else
1206 bigEndian = endianness;
1207
[802]1208 // PPS (POutPersist stream) Object Id initialisation
1209 pps_OId = 0;
[241]1210 // Output stream creation
1211 s = new ofstream(flnm.c_str(),ios::out | IOS_BIN);
1212
1213 // Header
[802]1214 PutRawBytes("SOS-SOPHYA-PPersistFile V2 ",32);
[241]1215 PutRawBytes(bigEndian
1216 ? "BIG-ENDIAN "
1217 : "LITTLE-ENDIAN ",32);
1218
1219// ---- GMT creation date of the file
1220 time_t tm = time(NULL);
1221 char datestring[33];
[742]1222 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
[241]1223 for(int i=l; i<32; i++) datestring[i] = ' ';
1224 datestring[32] = '\0';
1225 PutRawBytes(datestring, 32);
[802]1226 filename = flnm;
[219]1227}
1228
1229POutPersist::~POutPersist()
1230{
[241]1231 if (tags.size() == 0) {
[802]1232 PutRawUByte(PPS_EOF);
[241]1233 PutRawI8(-1);
1234 } else {
1235 int_8 tagPos;
1236#ifdef STREAMPOS_IS_CLASS
1237 tagPos = s->tellp().offset();
1238#else
1239 tagPos = s->tellp();
1240#endif
1241 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
1242 string name = (*i).first;
1243 int_8 pos = (*i).second;
[802]1244 PutRawUByte(PPS_TAG); // This is a tag
[241]1245 PutRawI8(pos); // position of previous tag
1246 PutRawI4(name.length()); // length of the name
1247 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
1248 }
[802]1249 PutRawUByte(PPS_EOF);
[241]1250 PutRawI8(tagPos);
1251 }
1252
1253 delete s; // Close the stream
[219]1254}
1255
1256
[241]1257void
1258POutPersist::WriteTag(string const& name)
[219]1259{
[241]1260 if (name.length() > MAXTAGLEN)
1261 throw ParmError("POutPersist::WriteTag tag name too long");
[219]1262
[241]1263 if (tags.find(name) != tags.end())
1264 throw DuplicateIdExc("POutPersist::WriteTag duplicate tag name");
1265
1266 // Get current file position
1267 int_8 tagPos;
1268
[219]1269 #ifdef STREAMPOS_IS_CLASS
[241]1270 tagPos = s->tellp().offset();
[219]1271 #else
[241]1272 tagPos = s->tellp();
[219]1273 #endif
[241]1274
1275 tags[name] = tagPos;
[802]1276 PutRawUByte(PPS_TAG_MARK); // This is a tag
1277 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
[219]1278}
1279
1280//++
1281// void POutPersist::PutByte(char& c)
1282// void POutPersist::PutBytes(void const* ptr, size_t bytes)
1283// void POutPersist::PutR4 (r_4 result)
1284// void POutPersist::PutR4s (r_4 const* tab, size_t n)
1285// void POutPersist::PutR8 (r_8 result)
1286// void POutPersist::PutR8s (r_8 const* tab, size_t n)
1287// void POutPersist::PutI2 (int_2 result)
1288// void POutPersist::PutI2s (int_2 const* tab, size_t n)
1289// void POutPersist::PutU2 (uint_2 result)
1290// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
1291// void POutPersist::PutI4 (int_4 result)
1292// void POutPersist::PutI4s (int_4 const* tab, size_t n)
1293// void POutPersist::PutU4 (uint_4 result)
1294// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
1295// void POutPersist::PutI8 (int_8 result)
1296// void POutPersist::PutI8s (int_8 const* tab, size_t n)
1297// void POutPersist::PutU8 (uint_8 result)
1298// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
[241]1299// void POutPersist::PutStr (string const&)
[219]1300// Ecriture de données portables.. Pour chaque type
1301// de données, on peut écrire une valeur, ou un tableau de valeurs.
1302// void POutPersist::PutLine(char const* ptr, size_t len)
1303// Ecriture d'une ligne de texte dans le fichier PPersist.
1304//--
1305
1306
1307
1308
1309void
[241]1310POutPersist::PutRawBytes(void const* ptr, size_t bytes)
1311{
1312 s->write((char const*)ptr, bytes);
1313}
1314
1315void
1316POutPersist::PutRawByte(char c)
1317{
1318 PutRawBytes(&c, 1);
1319}
1320
1321void
[802]1322POutPersist::PutRawUByte(unsigned char c)
1323{
1324 PutRawBytes(&c, 1);
1325}
1326
1327void
[241]1328POutPersist::PutRawI2 (int_2 val)
1329{
1330 if (bigEndian != IS_BIG_ENDIAN)
1331 bswap2(&val);
1332
1333 PutRawBytes(&val, sizeof(int_2));
1334}
1335
1336void
1337POutPersist::PutRawI4 (int_4 val)
1338{
1339 if (bigEndian != IS_BIG_ENDIAN)
1340 bswap4(&val);
1341
1342 PutRawBytes(&val, sizeof(int_4));
1343}
1344
1345void
1346POutPersist::PutRawI8 (int_8 val)
1347{
1348 if (bigEndian != IS_BIG_ENDIAN)
1349 bswap8(&val);
1350
1351 PutRawBytes(&val, sizeof(int_8));
1352}
1353
1354void
1355POutPersist::PutRawU8 (uint_8 val)
1356{
1357 if (bigEndian != IS_BIG_ENDIAN)
1358 bswap8(&val);
1359
1360 PutRawBytes(&val, sizeof(uint_8));
1361}
1362
1363void
[802]1364POutPersist::PutArrayTag(short datasz, size_t sz, short datatype)
1365// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
[241]1366{
[802]1367 if (sz <= 0x7fffffff) {
1368 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
[241]1369 PutRawI4(sz);
1370 } else {
[802]1371 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
[241]1372 PutRawU8(sz);
1373 }
1374}
1375
1376void
[219]1377POutPersist::PutByte(char c)
1378{
[802]1379 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
[241]1380 PutRawBytes(&c, 1);
[219]1381}
1382
[241]1383
1384
[219]1385void
1386POutPersist::PutBytes(void const* ptr, size_t bytes)
1387{
[802]1388 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
[241]1389 PutRawBytes(ptr, bytes);
[219]1390}
1391
1392void
1393POutPersist::PutR4 (r_4 val)
1394{
[802]1395 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
[241]1396
[219]1397 if (bigEndian != IS_BIG_ENDIAN)
1398 bswap4(&val);
1399
[241]1400 PutRawBytes(&val, sizeof(r_4));
[219]1401}
1402
1403void
1404POutPersist::PutR4s (r_4 const* tab, size_t n)
1405{
[802]1406 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
[241]1407
1408 if (bigEndian == IS_BIG_ENDIAN) {
1409 PutRawBytes(tab, n*sizeof(r_4));
1410 } else {
1411 for (unsigned int i=0; i<n; i++) {
1412 r_4 val = tab[i];
1413 bswap4(&val);
1414 PutRawBytes(&val, sizeof(r_4));
1415 }
1416 }
[219]1417}
1418
1419void
1420POutPersist::PutR8 (r_8 val)
1421{
[802]1422 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
[241]1423
[219]1424 if (bigEndian != IS_BIG_ENDIAN)
1425 bswap8(&val);
1426
[241]1427 PutRawBytes(&val, sizeof(r_8));
[219]1428}
1429
1430void
1431POutPersist::PutR8s (r_8 const* tab, size_t n)
1432{
[802]1433 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
[241]1434
1435 if (bigEndian == IS_BIG_ENDIAN) {
1436 PutRawBytes(tab, n*sizeof(r_8));
1437 } else {
1438 for (unsigned int i=0; i<n; i++) {
1439 r_8 val = tab[i];
1440 bswap8(&val);
1441 PutRawBytes(&val, sizeof(r_8));
1442 }
1443 }
[219]1444}
1445
1446void
1447POutPersist::PutI2 (int_2 val)
1448{
[802]1449 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
[241]1450
[219]1451 if (bigEndian != IS_BIG_ENDIAN)
1452 bswap2(&val);
1453
[241]1454 PutRawBytes(&val, sizeof(int_2));
[219]1455}
1456
1457void
1458POutPersist::PutI2s (int_2 const* tab, size_t n)
1459{
[802]1460 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
[241]1461
1462 if (bigEndian == IS_BIG_ENDIAN) {
1463 PutRawBytes(tab, n*sizeof(int_2));
1464 } else {
1465 for (unsigned int i=0; i<n; i++) {
1466 int_2 val = tab[i];
1467 bswap2(&val);
1468 PutRawBytes(&val, sizeof(int_2));
1469 }
1470 }
[219]1471}
1472
1473void
1474POutPersist::PutU2 (uint_2 val)
1475{
[802]1476 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
[241]1477
[219]1478 if (bigEndian != IS_BIG_ENDIAN)
1479 bswap2(&val);
1480
[241]1481 PutRawBytes(&val, sizeof(uint_2));
[219]1482}
1483
1484void
1485POutPersist::PutU2s (uint_2 const* tab, size_t n)
1486{
[802]1487 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
[241]1488
1489 if (bigEndian == IS_BIG_ENDIAN) {
1490 PutRawBytes(tab, n*sizeof(uint_2));
1491 } else {
1492 for (unsigned int i=0; i<n; i++) {
1493 uint_2 val = tab[i];
1494 bswap2(&val);
1495 PutRawBytes(&val, sizeof(uint_2));
1496 }
1497 }
[219]1498}
1499
1500void
1501POutPersist::PutI4 (int_4 val)
1502{
[802]1503 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
[241]1504
[219]1505 if (bigEndian != IS_BIG_ENDIAN)
1506 bswap4(&val);
1507
[241]1508 PutRawBytes(&val, sizeof(int_4));
[219]1509}
1510
1511void
1512POutPersist::PutI4s (int_4 const* tab, size_t n)
1513{
[802]1514 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
[241]1515
1516 if (bigEndian == IS_BIG_ENDIAN) {
1517 PutRawBytes(tab, n*sizeof(int_4));
1518 } else {
1519 for (unsigned int i=0; i<n; i++) {
1520 int_4 val = tab[i];
1521 bswap4(&val);
1522 PutRawBytes(&val, sizeof(int_4));
1523 }
1524 }
[219]1525}
1526
1527void
1528POutPersist::PutU4 (uint_4 val)
1529{
[802]1530 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
[241]1531
[219]1532 if (bigEndian != IS_BIG_ENDIAN)
1533 bswap4(&val);
1534
[241]1535 PutRawBytes(&val, sizeof(uint_4));
[219]1536}
1537
1538void
1539POutPersist::PutU4s (uint_4 const* tab, size_t n)
1540{
[802]1541 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
[241]1542
1543 if (bigEndian == IS_BIG_ENDIAN) {
1544 PutRawBytes(tab, n*sizeof(uint_4));
1545 } else {
1546 for (unsigned int i=0; i<n; i++) {
1547 uint_4 val = tab[i];
1548 bswap4(&val);
1549 PutRawBytes(&val, sizeof(uint_4));
1550 }
1551 }
[219]1552}
1553
1554void
1555POutPersist::PutI8 (int_8 val)
1556{
[802]1557 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
[241]1558
[219]1559 if (bigEndian != IS_BIG_ENDIAN)
1560 bswap8(&val);
1561
[241]1562 PutRawBytes(&val, sizeof(int_8));
[219]1563}
1564
1565void
1566POutPersist::PutI8s (int_8 const* tab, size_t n)
1567{
[802]1568 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
[241]1569
1570 if (bigEndian == IS_BIG_ENDIAN) {
1571 PutRawBytes(tab, n*sizeof(int_8));
1572 } else {
1573 for (unsigned int i=0; i<n; i++) {
1574 int_8 val = tab[i];
1575 bswap8(&val);
1576 PutRawBytes(&val, sizeof(int_8));
1577 }
1578 }
[219]1579}
1580
1581void
1582POutPersist::PutU8 (uint_8 val)
1583{
[802]1584 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
[241]1585
[219]1586 if (bigEndian != IS_BIG_ENDIAN)
1587 bswap8(&val);
1588
[241]1589 PutRawBytes(&val, sizeof(uint_8));
[219]1590}
1591
1592void
1593POutPersist::PutU8s (uint_8 const* tab, size_t n)
1594{
[802]1595 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
[241]1596
1597 if (bigEndian == IS_BIG_ENDIAN) {
1598 PutRawBytes(tab, n*sizeof(uint_8));
1599 } else {
1600 for (unsigned int i=0; i<n; i++) {
1601 uint_8 val = tab[i];
1602 bswap8(&val);
1603 PutRawBytes(&val, sizeof(uint_8));
1604 }
1605 }
[219]1606}
1607
1608void
[241]1609POutPersist::PutStr(string const& str)
1610{
[802]1611 PutRawUByte(PPS_STRING);
1612 PutRawI4(str.length());
[241]1613 PutRawBytes(str.c_str(), str.length());
1614}
1615
1616void
[219]1617POutPersist::PutLine(char const* ptr, size_t len)
1618{
[802]1619 string str = ptr;
1620 PutStr(str);
1621}
[241]1622
[802]1623
1624void
1625POutPersist::PutObject(AnyDataObj & o)
1626{
1627 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
1628 if (!f)
1629 throw NotFoundExc("PInPersist::PutObject() class not registered");
1630 PPersist* ppo = f();
1631 ppo->SetDataObj(o);
1632 PutPPObject(ppo);
[219]1633}
1634
[241]1635void
[802]1636POutPersist::PutObject(AnyDataObj & o, string tagname)
[241]1637{
[802]1638 WriteTag(tagname);
1639 PutObject(o);
1640}
[219]1641
[802]1642
1643void
1644POutPersist::PutPPObject(PPersist const* obj)
1645{
1646 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
1647
1648 // We have to write the object
1649 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
1650 PutRawUByte(PPS_OBJECT); // We write the Object Tag
1651 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
1652 PutRawU8(oid); // Write the PPS Object Id
[241]1653 obj->WriteSelf(*this);
[802]1654 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1655 PutRawU8(oid); // and again its PPS Object Id
[241]1656}
[219]1657
[241]1658bool
1659POutPersist::serializeNullAndRepeat(PPersist const* x)
[219]1660{
[241]1661 if (x == NULL) {
[802]1662 PutRawUByte(PPS_NULL);
[241]1663 return true;
1664 }
[219]1665
[802]1666 int_8 pos;
1667 uint_8 id = findObjectId(x, pos);
1668 if (id > 0) {
1669 PutRawUByte(PPS_REFERENCE);
1670 PutRawU8(id); // Writing the corresponding object Id
1671 PutRawI8(pos); // The original object position
[241]1672 return true;
1673 }
[219]1674
[802]1675 return false; // Object have to be written in stream ...
[219]1676}
1677
[802]1678uint_8
[241]1679POutPersist::assignObjectId(PPersist const* x)
[219]1680{
[802]1681 pps_OId += 16; // We keep the three first bytes for future usage
1682 // Bit 1 non zero -> Object can be referenced
1683 uint_8 id = pps_OId;
1684 uint_8 mid = x->getMemOId();
1685 if (mid > 0) {
1686 int_8 pos;
1687 if (findObjectId(x,pos) > 0)
1688 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
[821]1689 id += 1; // Bit 1 non zero -> Object can be referenced
[802]1690 objreftag rt;
1691 rt.ppsoid = id;
1692#ifdef STREAMPOS_IS_CLASS
1693 rt.ppspos = s->tellp().offset();
1694#else
1695 rt.ppspos = s->tellp();
1696#endif
1697 objList[mid] = rt;
1698 }
[241]1699 return id;
[219]1700}
1701
[802]1702uint_8
1703POutPersist::findObjectId(PPersist const* x, int_8 & pos)
[219]1704{
[802]1705 pos = -1;
1706 uint_8 mid = x->getMemOId();
1707 if (mid == 0) return(0);
1708 ObjList::iterator i = objList.find(mid);
1709 if (i == objList.end()) return 0;
1710 pos = (*i).second.ppspos;
1711 return (*i).second.ppsoid;
[219]1712}
1713
[241]1714
Note: See TracBrowser for help on using the repository browser.