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

Last change on this file since 2111 was 2111, checked in by ansari, 23 years ago

Erreur declaration strptime (const mal place - detecte par M. Reinecke) - Reza 17/7/2002

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