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

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

Mise au point du nouveau schema (Version=2) de PPersist - Mise en place

de tag complet pour toutes les donnees/objets ecrits - Gestion a peu
pres correct des objets references plusieurs fois, ecrit une seule fois.
Mecanisme d'enregistrement pour les DataObject associe et Methodes
(PutObject/GetObjet) facilitant l'ecriture/lecture de DataObject.
Separation du fichier de la classe FIO_NDataBlock<T>.

Reza03/04/2000

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