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

Last change on this file since 2459 was 2459, checked in by ansari, 22 years ago

Suite modifications PPersist - en particulier, utilisation des RawInOutStream - Reza 22 Nov 2003

File size: 46.4 KB
Line 
1#include "machdefs.h"
2#include <stdio.h>
3#include <sys/types.h>
4#include <time.h>
5#include "pexceptions.h"
6#include "ppersist.h"
7#include "anydataobj.h"
8#include <fstream>
9#include <iostream>
10#include <typeinfo>
11
12
13#ifdef __mac__
14#include "unixmac.h"
15#include <SIOUX.h>
16#endif
17
18// strptime n'est pas defini sous Linux - Reza Mars 2000
19#if defined(OS_LINUX) || defined(OS_MACOSX)
20extern "C" {
21char *strptime(const char *buf, const char *format, struct tm *tm);
22}
23#endif
24
25#define MAXTAGLEN 255
26
27//++
28// Class PIOPersist
29// Lib Outils++
30// include ppersist.h
31//
32// Root class for persistant files. Handles the registration of
33// persistant classes
34//--
35
36//++
37// Links See
38// PPersist
39// PInPersist
40// POutPersist
41//--
42
43
44MD5_CONTEXT PIOPersist::ctx;
45PIOPersist::ClassList * PIOPersist::ppclassList = NULL; // $CHECK$ Reza 26/04/99
46map<string, uint_8> * PIOPersist::ppclassNameList = NULL;
47map<string, uint_8> * PIOPersist::dobjclassNameList = NULL;
48
49//++
50void
51PIOPersist::Initialize()
52// Initialisation globale (objets statiques) $CHECK$ Reza 26/04/99
53//--
54{
55ppclassList = new PIOPersist::ClassList;
56ppclassNameList = new map<string, uint_8>;
57dobjclassNameList = new map<string, uint_8>;
58cout << " PIOPersist::Initialize() Starting Sophya Persistence management service " << endl;
59}
60
61//++
62void
63PIOPersist::RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f)
64//
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
69//
70//--
71{
72 if (ppclassList->size() && (ppclassList->find(classId) != ppclassList->end()) ) {
73 cerr << "RegisterClass : Error, " << hex << classId << dec
74 << " already registered." << endl;
75 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered (1)"));
76 }
77 if (ppclassNameList->size() && (ppclassNameList->find(ppclass_name) != ppclassNameList->end())) {
78 cerr << "RegisterClass : Error (2) " << ppclass_name
79 << " already registered." << endl;
80 throw(DuplicateIdExc("PIOPersist::RegisterPPHandlerClass() Already registered(2)"));
81 }
82
83 (*ppclassList)[classId] = f;
84 (*ppclassNameList)[ppclass_name] = classId;
85}
86
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{
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 }
104
105 (*dobjclassNameList)[class_name] = classId;
106}
107
108// class_typename should be typeid(DataObject).name(), to be
109// used by POutPersist::PutDataObject() methods.
110
111PIOPersist::ClassCreatorFunc
112PIOPersist::FindCreatorFunc(uint_8 classId)
113// Returns the PPersist class creator function for the specified classId
114{
115 ClassList::iterator i = ppclassList->find(classId);
116 if (i == ppclassList->end()) throw(NotFoundExc("PIOPersist::FindCreatorFunc() Not found classId"));
117 return (*i).second;
118}
119
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;
127
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
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
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//++
249// Links See
250// PInPersist
251// POutPersist
252// PIOPersist
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{
286 s.PutPPObject(this);
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
296// objet, utiliser PInPersist::ReadObject.
297// Il faut qu'on soit un objet ecrit
298//--
299{
300 // We should be the exact type
301 // Check tag value
302 unsigned char ppstype,ppstag;
303 s.GetTypeTag(ppstype);
304 if ( (ppstype != PInPersist::PPS_OBJECT) && ( ppstype != PInPersist::PPS_REFERENCE ) ) {
305 }
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)
323 }
324 else if ( ppstype == PInPersist::PPS_REFERENCE )
325 s.ReadReference(*this);
326
327 else throw FileFormatExc("PPersist::Read() : not an object in flow");
328
329}
330
331//++
332void
333PPersist::Write(POutPersist& s, string const& tag) const
334//
335// Ecrit l'objet dans le fichier PPersist avec un tag
336//--
337{
338 s.WriteNameTag(tag);
339 s.PutPPObject(this);
340}
341
342//++
343void
344PPersist::ReadAtTag(PInPersist& s, string const& tag)
345//
346// Lit l'objet à la position du tag numéro "tagid".
347//--
348{
349 if (!s.GotoNameTag(tag))
350 throw NotFoundExc("PPersist::ReadAtTag tag not found");
351 Read(s);
352}
353
354// Renvoie l'identificateur de l'objet - par defaut=0
355
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
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{
403 s = new RawInFileStream(flnm.c_str());
404
405 // Read and check header
406
407 char rbuf[36];
408 GetRawBytes(rbuf, 32);
409 if (strncmp(rbuf,"SOS-SOPHYA-PPersistFile", 23) != 0) {
410 throw FileFormatExc("PInPersist::PInPersist bad header");
411 }
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 }
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;
433 /* #if !(defined(__MWERKS__) || defined(OS_MACOSX)) RZ-DEL */
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
439 tm.tm_mon --;
440 tm.tm_year -= 1900;
441 #endif RZ-DEL */
442
443 creationdate = mktime(&tm);
444 filename = flnm; // keep the filename
445 seqread = true; // To flag non sequential reads
446 if (scan && s->isSeekable()) Scan();
447}
448
449
450
451PInPersist::~PInPersist()
452{
453 ObjList::iterator i;
454 for(i=objList.begin(); i!= objList.end(); i++)
455 if ((*i).second) delete (*i).second;
456 delete s;
457}
458
459
460string
461PInPersist::CreationDateStr()
462{
463 time_t cdt = CreationDate();
464 string cdate = ctime(&cdt);
465 return(cdate);
466}
467
468void
469PInPersist::Scan()
470{
471 // On cherche la liste des tags, a la fin du fichier
472
473 unsigned char ppstype;
474 int_8 debut;
475 debut = s->tellg();
476
477 s->seekg(-(sizeof(int_8)+1), ios::end);
478
479 GetTypeTag(ppstype);
480 if (ppstype != PPS_EOF)
481 throw FileFormatExc("PInPersist::Scan corrupted file, no eof entry at end of file");
482
483 int_8 pos;
484 GetRawI8(pos);
485 if (pos < 0) { // no tags
486 s->seekg(debut);
487 return;
488 }
489
490 char buffer[MAXTAGLEN+1];
491 s->seekg(pos);
492 while (true) {
493 GetTypeTag(ppstype);
494 if (ppstype == PPS_EOF) break;
495
496 if (ppstype != PPS_NAMETAG_TABLE)
497 throw FileFormatExc("PInPersist::Scan corrupted file, bad tag entry");
498
499 GetRawI8(pos);
500 int_4 len;
501 GetRawI4(len);
502 if (len > MAXTAGLEN)
503 throw FileFormatExc("PInPersist::Scan corrupted file, tag name too long");
504 GetRawBytes(buffer, len);
505 buffer[len] = '\0';
506
507 tags[buffer] = pos;
508 }
509 s->seekg(debut);
510}
511
512
513int
514PInPersist::NbNameTags()
515{
516 return tags.size();
517}
518
519bool
520PInPersist::GotoPositionTag(int_8 pos)
521{
522 s->seekg(pos);
523 int_8 tpos;
524 GetRawI8(tpos);
525 if (tpos != pos)
526 throw FileFormatExc("PInPersist::GotoPositionTag() - Wrong tag position!");
527 return true;
528}
529
530bool
531PInPersist::GotoNameTag(string const& name)
532{
533 map<string, int_8>::iterator i = tags.find(name);
534 if (i == tags.end())
535 return false;
536 // throw NotFoundExc("PInPersist::GotoNameTag tag not found");
537 s->seekg((*i).second);
538 seqread = false;
539 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
540 return(true);
541}
542
543
544bool
545PInPersist::GotoNameTagNum(int itag)
546{
547 if (itag<0 || itag >= (int)tags.size()) return false;
548 map<string, int_8>::iterator i = tags.begin();
549 for (int j=0; j<itag; j++) i++;
550 s->seekg((*i).second);
551 seqread = false;
552 // objList.clear(); $CHECK$ EA 171199 Ne pas faire ? Reza 03/2000 ?
553 return(true);
554}
555
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}
564
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
577static vector<string> * ret_tag_names = NULL;
578vector<string> const &
579PInPersist::GetNameTags()
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
588bool
589PInPersist::SkipToNextObject()
590{
591 // A FAIRE NOV 2003 - REZA
592 return true;
593}
594
595//++
596// void PInPersist::GetByte(char& c)
597// void PInPersist::GetBytes(void* ptr, size_t bytes)
598// void PInPersist::GetR4 (r_4& result)
599// void PInPersist::GetR4s (r_4* tab, size_t n)
600// void PInPersist::GetR8 (r_8& result)
601// void PInPersist::GetR8s (r_8* tab, size_t n)
602// void PInPersist::GetI2 (int_2& result)
603// void PInPersist::GetI2s (int_2* tab, size_t n)
604// void PInPersist::GetU2 (uint_2& result)
605// void PInPersist::GetU2s (uint_2* tab, size_t n)
606// void PInPersist::GetI4 (int_4& result)
607// void PInPersist::GetI4s (int_4* tab, size_t n)
608// void PInPersist::GetU4 (uint_4& result)
609// void PInPersist::GetU4s (uint_4* tab, size_t n)
610// void PInPersist::GetI8 (int_8& result)
611// void PInPersist::GetI8s (int_8* tab, size_t n)
612// void PInPersist::GetU8 (uint_8& result)
613// void PInPersist::GetU8s (uint_8* tab, size_t n)
614// Lecture de données portables depuis le fichier PPersist. Pour chaque type
615// de données, on peut lire une valeur, ou un tableau de valeurs.
616// void PInPersist::GetLine(char* ptr, size_t len)
617// Lecture d'une ligne de texte depuis le fichier PPersist.
618//--
619
620
621void
622PInPersist::GetTypeTag(unsigned char& c)
623{
624 int_8 tpos;
625 c = PPS_NAMETAG_MARK;
626 while ( (c == PPS_NAMETAG_MARK) || (c == PPS_POSTAG_MARK) ) {
627 GetRawUByte(c);
628 if (c == PPS_POSTAG_MARK) GetRawI8(tpos);
629 }
630 // while (c == PPS_NAMETAG_MARK) { Il ne faut plus faire ca !
631 // objList.clear(); $CHECK$ Reza 03/2000
632 // GetRawByte(c);
633 // }
634}
635
636
637void
638PInPersist::GetRawByte(char& c)
639{
640 GetRawBytes(&c, 1);
641}
642
643void
644PInPersist::GetRawUByte(unsigned char& c)
645{
646 GetRawBytes(&c, 1);
647}
648
649void
650PInPersist::GetRawBytes(void* ptr, size_t bytes)
651{
652 s->read((char*)ptr, bytes);
653}
654
655void
656PInPersist::GetRawI2 (int_2& result)
657{
658 GetRawBytes(&result, sizeof(int_2));
659 if (bigEndian != IS_BIG_ENDIAN)
660 bswap2(&result);
661}
662
663void
664PInPersist::GetRawI4 (int_4& result)
665{
666 GetRawBytes(&result, sizeof(int_4));
667 if (bigEndian != IS_BIG_ENDIAN)
668 bswap4(&result);
669}
670
671void
672PInPersist::GetRawI8 (int_8& result)
673{
674 GetRawBytes(&result, sizeof(int_8));
675 if (bigEndian != IS_BIG_ENDIAN)
676 bswap8(&result);
677}
678
679void
680PInPersist::GetRawU8 (uint_8& result)
681{
682 GetRawBytes(&result, sizeof(uint_8));
683 if (bigEndian != IS_BIG_ENDIAN)
684 bswap8(&result);
685}
686
687void
688PInPersist::CheckTag(short datasz, short datatype)
689// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
690{
691 unsigned char ppstype;
692 GetTypeTag(ppstype);
693 if (ppstype != PPS_SIMPLE + datasz + datatype)
694 throw FileFormatExc("PInPersist::CheckTag bad type in ppersist file");
695}
696
697void
698PInPersist::CheckArrayTag(short datasz, size_t sz, short datatype)
699// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
700{
701 unsigned char ppstype;
702 GetTypeTag(ppstype);
703 size_t filesz;
704 if (sz <= 0x7fffffff) {
705 if (ppstype != PPS_SIMPLE_ARRAY4 + datasz + datatype)
706 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
707 int_4 ff;
708 GetRawI4(ff); filesz=ff;
709 } else {
710 if (ppstype != PPS_SIMPLE_ARRAY8 + datasz + datatype)
711 throw FileFormatExc("PInPersist::CheckArrayTag bad type in ppersist file");
712 uint_8 ff;
713 GetRawU8(ff); filesz=ff;
714 }
715 if (filesz != sz)
716 throw FileFormatExc("PInPersist::CheckArrayTag bad array size in ppersist file");
717}
718
719void
720PInPersist::GetByte(char& c)
721{
722 CheckTag(1,PPS_DATATYPE_CHAR);
723 GetRawBytes(&c, 1);
724}
725
726
727void
728PInPersist::GetBytes(void* ptr, size_t bytes)
729{
730 CheckArrayTag(1, bytes, PPS_DATATYPE_CHAR);
731 GetRawBytes(ptr, bytes);
732}
733void
734PInPersist::GetR4 (r_4& result)
735{
736 CheckTag(4,PPS_DATATYPE_FLOAT);
737 GetRawBytes(&result, sizeof(r_4));
738 if (bigEndian != IS_BIG_ENDIAN)
739 bswap4(&result);
740}
741
742
743void
744PInPersist::GetR4s (r_4* tab, size_t n)
745{
746 CheckArrayTag(4,n,PPS_DATATYPE_FLOAT);
747 GetRawBytes(tab, n*sizeof(r_4));
748 if (bigEndian == IS_BIG_ENDIAN) return;
749
750 for (unsigned int i=0; i<n; i++)
751 bswap4(tab+i);
752
753 return;
754}
755
756void
757PInPersist::GetR8 (r_8& result)
758{
759 CheckTag(8,PPS_DATATYPE_FLOAT);
760 GetRawBytes(&result, sizeof(r_8));
761 if (bigEndian != IS_BIG_ENDIAN)
762 bswap8(&result);
763}
764
765void
766PInPersist::GetR8s (r_8* tab, size_t n)
767{
768 CheckArrayTag(8,n,PPS_DATATYPE_FLOAT);
769 GetRawBytes(tab, n*sizeof(r_8));
770 if (bigEndian == IS_BIG_ENDIAN) return;
771
772 for (unsigned int i=0; i<n; i++)
773 bswap8(tab+i);
774
775 return;
776}
777
778void
779PInPersist::GetI1 (int_1& result)
780{
781 CheckTag(1,PPS_DATATYPE_INTEGER);
782 GetRawBytes(&result, sizeof(int_1));
783}
784
785void
786PInPersist::GetI1s (int_1* tab, size_t n)
787{
788 CheckArrayTag(1,n,PPS_DATATYPE_INTEGER);
789 GetRawBytes(tab, n*sizeof(int_1));
790}
791
792void
793PInPersist::GetU1 (uint_1& result)
794{
795 CheckTag(1,PPS_DATATYPE_UNSIGNED);
796 GetRawBytes(&result, sizeof(uint_1));
797}
798
799void
800PInPersist::GetU1s (uint_1* tab, size_t n)
801{
802 CheckArrayTag(1,n,PPS_DATATYPE_UNSIGNED);
803 GetRawBytes(tab, n*sizeof(uint_1));
804}
805
806void
807PInPersist::GetI2 (int_2& result)
808{
809 CheckTag(2,PPS_DATATYPE_INTEGER);
810 GetRawBytes(&result, sizeof(int_2));
811 if (bigEndian != IS_BIG_ENDIAN)
812 bswap2(&result);
813}
814
815void
816PInPersist::GetI2s (int_2* tab, size_t n)
817{
818 CheckArrayTag(2,n,PPS_DATATYPE_INTEGER);
819 GetRawBytes(tab, n*sizeof(int_2));
820 if (bigEndian == IS_BIG_ENDIAN) return;
821
822 for (unsigned int i=0; i<n; i++)
823 bswap2(tab+i);
824
825 return;
826}
827
828void
829PInPersist::GetU2 (uint_2& result)
830{
831 CheckTag(2,PPS_DATATYPE_UNSIGNED);
832 GetRawBytes(&result, sizeof(uint_2));
833 if (bigEndian != IS_BIG_ENDIAN)
834 bswap2(&result);
835}
836
837void
838PInPersist::GetU2s (uint_2* tab, size_t n)
839{
840 CheckArrayTag(2,n,PPS_DATATYPE_UNSIGNED);
841 GetRawBytes(tab, n*sizeof(uint_2));
842 if (bigEndian == IS_BIG_ENDIAN) return;
843
844 for (unsigned int i=0; i<n; i++)
845 bswap2(tab+i);
846
847 return;
848}
849
850void
851PInPersist::GetI4 (int_4& result)
852{
853 CheckTag(4,PPS_DATATYPE_INTEGER);
854 GetRawBytes(&result, sizeof(int_4));
855 if (bigEndian != IS_BIG_ENDIAN)
856 bswap4(&result);
857}
858
859void
860PInPersist::GetI4s (int_4* tab, size_t n)
861{
862 CheckArrayTag(4,n,PPS_DATATYPE_INTEGER);
863 GetRawBytes(tab, n*sizeof(int_4));
864 if (bigEndian == IS_BIG_ENDIAN) return;
865
866 for (unsigned int i=0; i<n; i++)
867 bswap4(tab+i);
868
869 return;
870}
871
872void
873PInPersist::GetU4 (uint_4& result)
874{
875 CheckTag(4,PPS_DATATYPE_UNSIGNED);
876 GetRawBytes(&result, sizeof(uint_4));
877 if (bigEndian != IS_BIG_ENDIAN)
878 bswap4(&result);
879}
880
881void
882PInPersist::GetU4s (uint_4* tab, size_t n)
883{
884 CheckArrayTag(4,n,PPS_DATATYPE_UNSIGNED);
885 GetRawBytes(tab, n*sizeof(uint_4));
886 if (bigEndian == IS_BIG_ENDIAN) return;
887
888 for (unsigned int i=0; i<n; i++)
889 bswap4(tab+i);
890
891 return;
892}
893
894
895void
896PInPersist::GetI8 (int_8& result)
897{
898 CheckTag(8,PPS_DATATYPE_INTEGER);
899 GetRawBytes(&result, sizeof(int_8));
900 if (bigEndian != IS_BIG_ENDIAN)
901 bswap8(&result);
902}
903
904void
905PInPersist::GetI8s (int_8* tab, size_t n)
906{
907 CheckArrayTag(8,n,PPS_DATATYPE_INTEGER);
908 GetRawBytes(tab, n*sizeof(int_8));
909 if (bigEndian == IS_BIG_ENDIAN) return;
910
911 for (unsigned int i=0; i<n; i++)
912 bswap8(tab+i);
913
914 return;
915}
916
917void
918PInPersist::GetU8 (uint_8& result)
919{
920 CheckTag(8,PPS_DATATYPE_UNSIGNED);
921 GetRawBytes(&result, sizeof(uint_8));
922 if (bigEndian != IS_BIG_ENDIAN)
923 bswap8(&result);
924}
925
926void
927PInPersist::GetU8s (uint_8* tab, size_t n)
928{
929 CheckArrayTag(8,n,PPS_DATATYPE_UNSIGNED);
930 GetRawBytes(tab, n*sizeof(uint_8));
931 if (bigEndian == IS_BIG_ENDIAN) return;
932
933 for (unsigned int i=0; i<n; i++)
934 bswap8(tab+i);
935
936 return;
937}
938
939
940void
941PInPersist::GetLine(char* ptr, size_t len)
942{
943 string str;
944 GetStr(str);
945 strncpy(ptr, str.c_str(), len);
946 ptr[len] = '\0';
947}
948
949void
950PInPersist::GetStr(string& str)
951{
952 unsigned char ppstype;
953 GetTypeTag(ppstype);
954 if (ppstype != PPS_STRING)
955 throw FileFormatExc("PInPersist::GetStr bad type in ppersist file");
956 int_4 len;
957 GetRawI4(len);
958 char * buff = new char[len+1];
959 GetRawBytes(buff, len);
960 buff[len] = '\0';
961 str = buff;
962 delete[] buff;
963}
964
965void
966PInPersist::GetZ4 (complex<r_4>& result)
967{
968 CheckTag(4,PPS_DATATYPE_COMPLEX);
969 r_4 reim[2];
970 GetRawBytes(reim, 2*sizeof(r_4));
971 if (bigEndian != IS_BIG_ENDIAN) {
972 bswap4(reim);
973 bswap4(reim+1);
974 }
975 result = complex<r_4>(reim[0], reim[1]);
976}
977
978void
979PInPersist::GetZ4s (complex<r_4>* tab, size_t n)
980{
981 CheckArrayTag(4,n,PPS_DATATYPE_COMPLEX);
982 GetRawBytes(tab, n*2*sizeof(r_4));
983 if (bigEndian == IS_BIG_ENDIAN) return;
984
985 r_4 * p = (r_4 *)tab;
986 for (unsigned int i=0; i<n; i++) {
987 bswap4(p); p++;
988 bswap4(p); p++;
989 }
990 return;
991}
992
993void
994PInPersist::GetZ8 (complex<r_8>& result)
995{
996 CheckTag(8,PPS_DATATYPE_COMPLEX);
997 r_8 reim[2];
998 GetRawBytes(reim, 2*sizeof(r_8));
999 if (bigEndian != IS_BIG_ENDIAN) {
1000 bswap8(reim);
1001 bswap8(reim+1);
1002 }
1003 result = complex<r_8>(reim[0], reim[1]);
1004}
1005
1006void
1007PInPersist::GetZ8s (complex<r_8>* tab, size_t n)
1008{
1009 CheckArrayTag(8,n,PPS_DATATYPE_COMPLEX);
1010 GetRawBytes(tab, n*2*sizeof(r_8));
1011 if (bigEndian == IS_BIG_ENDIAN) return;
1012
1013 r_8 * p = (r_8 *)tab;
1014 for (unsigned int i=0; i<n; i++) {
1015 bswap8(p); p++;
1016 bswap8(p); p++;
1017 }
1018 return;
1019}
1020
1021
1022void
1023PInPersist::GetPosTagTable(int_8* ptab, size_t sz)
1024{
1025 unsigned char ppstype;
1026 GetTypeTag(ppstype);
1027 if (ppstype != PPS_POSTAG_TABLE)
1028 throw FileFormatExc("PInPersist::GetPosTagTable bad type in ppersist stream");
1029 int_4 tsz;
1030 GetRawI4(tsz);
1031 if (tsz != sz)
1032 throw FileFormatExc("PInPersist::GetPosTagTable Size mismatch ");
1033 for(int kk=0; kk<tsz; kk++)
1034 GetRawI8(ptab[kk]);
1035 return;
1036}
1037
1038void
1039PInPersist::GetPosTagTable(vector<int_8>& ptab)
1040{
1041 unsigned char ppstype;
1042 GetTypeTag(ppstype);
1043 if (ppstype != PPS_POSTAG_TABLE)
1044 throw FileFormatExc("PInPersist::GetPosTagTable bad type in ppersist stream");
1045 ptab.clear();
1046 int_4 tsz;
1047 GetRawI4(tsz);
1048 int_8 tpos;
1049 for(int kk=0; kk<tsz; kk++) {
1050 GetRawI8(tpos);
1051 ptab.push_back(tpos);
1052 }
1053 return;
1054}
1055
1056PPersist*
1057PInPersist::ReadObject()
1058{
1059 return(GetPPObject());
1060}
1061
1062void
1063PInPersist::GetObject(AnyDataObj & o)
1064{
1065 GetPPObject(&o);
1066 return;
1067}
1068
1069void
1070PInPersist::GetObject(AnyDataObj & o, string tagname)
1071{
1072 GotoNameTag(tagname);
1073 GetPPObject(&o);
1074 return;
1075}
1076
1077PPersist*
1078PInPersist::GetPPObject(AnyDataObj * po)
1079{
1080 // Get tag
1081 unsigned char ppstype;
1082 GetTypeTag(ppstype);
1083 if (ppstype != PPS_OBJECT && ppstype != PPS_REFERENCE && ppstype != PPS_NULL) {
1084 throw FileFormatExc("PInPersist::ReadObject : not an object in flow");
1085 }
1086
1087 if (ppstype == PPS_NULL) {
1088 return NULL;
1089 } else if (ppstype == PPS_OBJECT) {
1090 // Get class id
1091 uint_8 classId;
1092 GetRawU8(classId);
1093 uint_8 oid,oid2;
1094 GetRawU8(oid);
1095
1096 // Get factory method
1097 ClassCreatorFunc f = FindCreatorFunc(classId);
1098 if (!f) {
1099 throw NotFoundExc("PInPersist::ReadObject class not registered");
1100 }
1101
1102 // Create object
1103 PPersist* object = f();
1104 // If a DataObject was specified , we assign it to the PPersistObject
1105 if (po != NULL) object->SetDataObj(*po);
1106
1107 object->ReadSelf(*this);
1108 unsigned char ppstag;
1109 // Read the ENDOBJECT
1110 GetRawUByte(ppstag);
1111 if (ppstag != PPS_ENDOBJECT)
1112 throw FileFormatExc("PInPersist::ReadObject No PPS_ENDOBJECT tag");
1113 GetRawU8(oid2);
1114 if (oid2 != oid)
1115 throw FileFormatExc("PInPersist::ReadObject Inconsistent PPS-OId at PPS_ENDOBJECT ");
1116
1117 KeepOId(oid, *object);
1118 return object;
1119 }
1120 else if (ppstype == PPS_REFERENCE)
1121 return ReadReference();
1122
1123 else throw FileFormatExc("PInPersist::ReadObject invalide Tag Type !");
1124}
1125
1126
1127void
1128PInPersist::AnalyseTags(int lev)
1129{
1130 unsigned char ppstag=0;
1131 unsigned char ppst1,ppst2,ppst3,ppst30;
1132 int_8 cpos,fsize;
1133 uint_8 ui8,cid,oid;
1134 int_4 i4;
1135 int_8 i8;
1136 char * buff;
1137 string str;
1138
1139 cout << "\n ---------------------------------------------------------- " << endl;
1140 cout << " PInPersist::AnalyseTags(Level= " << lev << ")" << endl;
1141
1142
1143 cpos = s->tellg();
1144 s->seekg(0,ios::end);
1145 fsize = s->tellg();
1146 s->seekg(cpos,ios::beg);
1147
1148 cout << " Version= " << Version() << " FileSize= " << fsize
1149 << " Creation Date= " << CreationDateStr() << endl;
1150
1151 uint_8 totntags = 0;
1152 bool eofok = false;
1153
1154 while ( (ppstag != PPS_EOF) && (cpos < fsize) ) {
1155 cpos = s->tellg();
1156 GetRawUByte(ppstag);
1157 totntags++;
1158
1159 ppst1 = ppstag&0x0f; // bits 0123
1160 ppst2 = ppstag&0x30; // bits 45
1161 ppst3 = ppstag&0xc0; // bits 67
1162 ppst30 = ppstag&0xc1; // bits 0 67
1163 if ((ppst2 == 0) && (ppst3 == 0) ) {
1164 switch (ppst1) {
1165
1166 case PPS_NULL :
1167 if (lev > 1) cout << "<PPS_NULL> tag at position " << hex << cpos << dec << endl;
1168 break;
1169
1170 case PPS_STRING :
1171 GetRawI4(i4);
1172 if (lev > 1) cout << "<PPS_STRING> tag at position " << hex << cpos << dec
1173 << " Length=" << i4 << endl;
1174 s->seekg(i4,ios::cur);
1175 break;
1176
1177 case PPS_OBJECT :
1178 GetRawU8(cid);
1179 GetRawU8(oid);
1180 cout << "<PPS_OBJECT> tag at position " << hex << cpos << " ClassId= " << cid
1181 << " ObjectId= " << oid << dec << endl;
1182 break;
1183
1184 case PPS_REFERENCE :
1185 GetRawU8(oid);
1186 GetRawI8(i8);
1187 cout << "<PPS_REFERENCE> tag at position " << hex << cpos << " ObjectId= "
1188 << oid << " OrigPos=" << i8 << dec << endl;
1189 break;
1190
1191 case PPS_NAMETAG_MARK :
1192 cout << "<PPS_NAMETAG_MARK> tag at position " << hex << cpos << dec << endl;
1193 break;
1194
1195 case PPS_POSTAG_MARK :
1196 GetRawI8(i8);
1197 cout << "<PPS_POSTAG_MARK> tag at position " << hex << cpos
1198 << " TPos=" << i8 << dec << endl;
1199 break;
1200
1201 case PPS_ENDOBJECT :
1202 GetRawU8(oid);
1203 cout << "<PPS_ENDOBJECT> tag at position " << hex << cpos << " ObjectId= "
1204 << oid << dec << endl;
1205 break;
1206
1207 case PPS_POSTAG_TABLE :
1208 GetRawI4(i4);
1209 for(int kkt=0; kkt<i4; kkt++) GetRawI8(i8);
1210 cout << "<PPS_POSTAG_TABLE> tag at position " << hex << cpos << dec << endl;
1211 break;
1212
1213 case PPS_NAMETAG_TABLE :
1214 GetRawI8(i8);
1215 GetRawI4(i4);
1216 buff = new char[i4+1];
1217 GetRawBytes(buff, i4);
1218 buff[i4] = '\0'; str = buff;
1219 delete[] buff;
1220 cout << "<PPS_TAG> tag at position " << hex << cpos << dec
1221 << " Name= " << str << endl;
1222 break;
1223
1224 case PPS_EOF :
1225 GetRawI8(i8);
1226 cout << "<PPS_EOF> tag at position " << hex << cpos
1227 << " TagPos=" << i8 << dec << endl;
1228 eofok = true;
1229 break;
1230
1231 default :
1232 cerr << " ERROR : Unexpected tag value " << hex << ppstag
1233 << " At position" << cpos << dec << endl;
1234 throw FileFormatExc("PInPersist::AnalyseTags() - Unexpected tag value !");
1235 }
1236 }
1237 else {
1238 string dtype = "???? x";
1239 if (ppst30 == PPS_DATATYPE_COMPLEX) dtype = "COMPLEX x";
1240 else if (ppst3 == PPS_DATATYPE_CHAR) dtype = "CHAR x";
1241 else if (ppst3 == PPS_DATATYPE_FLOAT) dtype = "FLOAT x";
1242 else if (ppst3 == PPS_DATATYPE_INTEGER) dtype = "INTEGER x";
1243 else if (ppst3 == PPS_DATATYPE_UNSIGNED) dtype = "UNSIGNED x";
1244 int_4 dsize = ppst1;
1245 int_4 dsizeskip = dsize;
1246 if (ppst30 == PPS_DATATYPE_COMPLEX) {
1247 dsize--;
1248 dsizeskip = 2*dsize;
1249 }
1250 char sb[16];
1251 sprintf(sb, "%d", dsize);
1252 dtype += sb;
1253
1254 switch (ppst2) {
1255
1256 case PPS_SIMPLE :
1257 if (lev > 2) cout << "<PPS_SIMPLE> tag at position " << hex << cpos << dec
1258 << " DataType=" << dtype << endl;
1259 s->seekg(dsizeskip, ios::cur);
1260 break;
1261
1262 case PPS_SIMPLE_ARRAY4 :
1263 GetRawI4(i4);
1264 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY4> tag at position " << hex << cpos << dec
1265 << " DataType=" << dtype << " NElts= " << i4 << endl;
1266 s->seekg((int_8)dsizeskip*(int_8)i4, ios::cur);
1267 break;
1268
1269 case PPS_SIMPLE_ARRAY8 :
1270 GetRawU8(ui8);
1271 if (lev > 0) cout << "<PPS_SIMPLE_ARRAY8> tag at position " << hex << cpos << dec
1272 << " DataType=" << dtype << " NElts= " << ui8 << endl;
1273 s->seekg((int_8)dsizeskip*ui8, ios::cur);
1274 break;
1275 }
1276 }
1277 }
1278 if (!eofok)
1279 throw FileFormatExc("PInPersist::AnalyseTags() - Not found <PPS_EOF> tag ");
1280
1281 cout << " PInPersist::AnalyseTags() - End - Total Number of Tags= " << totntags << endl;
1282 cout << " ---------------------------------------------------------- \n" << endl;
1283 return;
1284}
1285
1286void
1287PInPersist::ReadReference(PPersist & ppo)
1288{
1289 PPersist * pr = ReadReference();
1290 ppo.ShareDataReference(*pr);
1291}
1292
1293
1294PPersist *
1295PInPersist::ReadReference()
1296{
1297 uint_8 oid;
1298 int_8 pos;
1299 GetRawU8(oid);
1300 GetRawI8(pos);
1301 // cerr << " DBG - PInPersist::ReadReference-A " << oid << " Pos= " << pos << endl;
1302 map<uint_8, PPersist *>::iterator i = objList.find(oid);
1303 if (i != objList.end()) return (*i).second;
1304 else { // We may have skeeped it !
1305 // Let's try to read it
1306 int_8 cpos;
1307 cpos = s->tellg();
1308 s->seekg(pos);
1309 PPersist* ppo = ReadObject();
1310 s->seekg(cpos);
1311 delete ppo;
1312 // cerr << " DBG - PInPersist::ReadReference-B ... " << endl;
1313
1314 map<uint_8, PPersist *>::iterator i2 = objList.find(oid);
1315 if (i2 == objList.end())
1316 throw FileFormatExc("PInPersist::ReadReference() Not found PPS_OId ");
1317 return (*i2).second;
1318 }
1319}
1320
1321
1322void
1323PInPersist::KeepOId(uint_8 oid, PPersist & ppo)
1324{
1325 if ((oid&0x1) == 0) return; // This is not an object which can be referenced
1326 // cerr << " DBG - PInPersist::KeepOId() " << oid << endl;
1327 if ((objList.size() > 0) && (objList.find(oid) != objList.end()) ) {
1328 // Ceci ne devrait arriver que si on lit dans le desordre (avec GotoNameTag)
1329 // et pas avec une lecture sequentielle ... Reza 03/2000
1330 // cerr << "PInPersist::KeepOId()/Warning - already present PPS_ObjectId ! " << oid << endl;
1331 if (seqread) throw FileFormatExc("PInPersist::KeepOId() already present PPS_ObjectId ");
1332 PPersist *pp = (*objList.find(oid)).second;
1333 ppo.ShareDataReference(*pp);
1334 }
1335 else {
1336 PPersist * npp = ppo.CloneSharedReference();
1337 if (npp == NULL) throw PError("PInPersist::KeepOId() NULL returned by PPersist.Clone() ! ");
1338 objList[oid] = npp;
1339 }
1340 return;
1341}
1342
1343//++
1344// Class POutPersist
1345// Lib Outils++
1346// include ppersist.h
1347//
1348// Fichier d'objets persistants, en écriture.
1349//--
1350
1351
1352//++
1353// POutPersist(string const& flnm, int endianness = PPersist::PPS_NATIVE)
1354//
1355// Crée un nouveau fichier ppersist. Par défaut, il est petit=boutien
1356// sur machines petit-boutiennes, et gros-boutien sur machines
1357// gros-boutiennes. On peut explicitement spécifier PPersist::PPS_LITTLE_ENDIAN
1358// ou PPersist::PPS_BIG_ENDIAN.
1359//--
1360POutPersist::POutPersist(string const& flnm, int endianness)
1361{
1362 if (endianness == -1)
1363 bigEndian = IS_BIG_ENDIAN;
1364 else
1365 bigEndian = endianness;
1366
1367 // PPS (POutPersist stream) Object Id initialisation
1368 pps_OId = 0;
1369 // Output stream creation
1370 s = new RawOutFileStream(flnm.c_str());
1371 version = 3;
1372 // Header
1373 PutRawBytes("SOS-SOPHYA-PPersistFile V3 ",32);
1374 PutRawBytes(bigEndian
1375 ? "BIG-ENDIAN "
1376 : "LITTLE-ENDIAN ",32);
1377
1378// ---- GMT creation date of the file
1379 time_t tm = time(NULL);
1380 char datestring[33];
1381 int l=strftime(datestring,32,"%d/%m/%Y %H:%M:%S GMT",gmtime(&tm));
1382 for(int i=l; i<32; i++) datestring[i] = ' ';
1383 datestring[32] = '\0';
1384 PutRawBytes(datestring, 32);
1385 filename = flnm;
1386}
1387
1388POutPersist::~POutPersist()
1389{
1390 if (tags.size() == 0) {
1391 PutRawUByte(PPS_EOF);
1392 PutRawI8(-1);
1393 } else {
1394 int_8 tagPos;
1395 tagPos = s->tellp();
1396 for (map<string,int_8>::iterator i = tags.begin(); i != tags.end(); i++) {
1397 string name = (*i).first;
1398 int_8 pos = (*i).second;
1399 PutRawUByte(PPS_NAMETAG_TABLE); // This is a tag
1400 PutRawI8(pos); // position of previous tag
1401 PutRawI4(name.length()); // length of the name
1402 PutRawBytes(name.c_str(), name.length()); // name, without final "0".
1403 }
1404 PutRawUByte(PPS_EOF);
1405 PutRawI8(tagPos);
1406 }
1407
1408 delete s; // Close the stream
1409}
1410
1411int_8
1412POutPersist::WritePositionTag()
1413{
1414 int_8 tagpos;
1415 tagpos = s->tellp();
1416 PutRawByte(PPS_POSTAG_MARK);
1417 PutI8(tagpos);
1418 return(tagpos);
1419}
1420
1421void
1422POutPersist::WriteNameTag(string const& name)
1423{
1424 if (name.length() > MAXTAGLEN)
1425 throw ParmError("POutPersist::WriteNameTag tag name too long");
1426
1427 if (tags.find(name) != tags.end())
1428 throw DuplicateIdExc("POutPersist::WriteNameTag duplicate tag name");
1429
1430 // Get current file position
1431 int_8 tagPos;
1432 tagPos = s->tellp();
1433
1434 tags[name] = tagPos;
1435 PutRawUByte(PPS_NAMETAG_MARK); // This is a tag
1436 // objList.clear(); // $CHECK$ EA 171199 - Ne pas faire ? Reza 03/2000
1437}
1438
1439//++
1440// void POutPersist::PutByte(char& c)
1441// void POutPersist::PutBytes(void const* ptr, size_t bytes)
1442// void POutPersist::PutR4 (r_4 result)
1443// void POutPersist::PutR4s (r_4 const* tab, size_t n)
1444// void POutPersist::PutR8 (r_8 result)
1445// void POutPersist::PutR8s (r_8 const* tab, size_t n)
1446// void POutPersist::PutI2 (int_2 result)
1447// void POutPersist::PutI2s (int_2 const* tab, size_t n)
1448// void POutPersist::PutU2 (uint_2 result)
1449// void POutPersist::PutU2s (uint_2 const* tab, size_t n)
1450// void POutPersist::PutI4 (int_4 result)
1451// void POutPersist::PutI4s (int_4 const* tab, size_t n)
1452// void POutPersist::PutU4 (uint_4 result)
1453// void POutPersist::PutU4s (uint_4 const* tab, size_t n)
1454// void POutPersist::PutI8 (int_8 result)
1455// void POutPersist::PutI8s (int_8 const* tab, size_t n)
1456// void POutPersist::PutU8 (uint_8 result)
1457// void POutPersist::PutU8s (uint_8 const* tab, size_t n)
1458// void POutPersist::PutStr (string const&)
1459// Ecriture de données portables.. Pour chaque type
1460// de données, on peut écrire une valeur, ou un tableau de valeurs.
1461// void POutPersist::PutLine(char const* ptr, size_t len)
1462// Ecriture d'une ligne de texte dans le fichier PPersist.
1463//--
1464
1465
1466
1467
1468void
1469POutPersist::PutRawBytes(void const* ptr, size_t bytes)
1470{
1471 s->write((char const*)ptr, bytes);
1472}
1473
1474void
1475POutPersist::PutRawByte(char c)
1476{
1477 PutRawBytes(&c, 1);
1478}
1479
1480void
1481POutPersist::PutRawUByte(unsigned char c)
1482{
1483 PutRawBytes(&c, 1);
1484}
1485
1486void
1487POutPersist::PutRawI2 (int_2 val)
1488{
1489 if (bigEndian != IS_BIG_ENDIAN)
1490 bswap2(&val);
1491
1492 PutRawBytes(&val, sizeof(int_2));
1493}
1494
1495void
1496POutPersist::PutRawI4 (int_4 val)
1497{
1498 if (bigEndian != IS_BIG_ENDIAN)
1499 bswap4(&val);
1500
1501 PutRawBytes(&val, sizeof(int_4));
1502}
1503
1504void
1505POutPersist::PutRawI8 (int_8 val)
1506{
1507 if (bigEndian != IS_BIG_ENDIAN)
1508 bswap8(&val);
1509
1510 PutRawBytes(&val, sizeof(int_8));
1511}
1512
1513void
1514POutPersist::PutRawU8 (uint_8 val)
1515{
1516 if (bigEndian != IS_BIG_ENDIAN)
1517 bswap8(&val);
1518
1519 PutRawBytes(&val, sizeof(uint_8));
1520}
1521
1522void
1523POutPersist::PutArrayTag(short datasz, size_t sz, short datatype)
1524// datatype = PPS_DATATYPE_CHAR or PPS_DATATYPE_FLOAT or PPS_DATATYPE_INTEGER or PPS_DATATYPE_UNSIGNED
1525{
1526 if (sz <= 0x7fffffff) {
1527 PutRawUByte(PPS_SIMPLE_ARRAY4 + datasz + datatype);
1528 PutRawI4(sz);
1529 } else {
1530 PutRawUByte(PPS_SIMPLE_ARRAY8 + datasz + datatype);
1531 PutRawU8(sz);
1532 }
1533}
1534
1535void
1536POutPersist::PutByte(char c)
1537{
1538 PutRawByte(PPS_SIMPLE + 1 + PPS_DATATYPE_CHAR);
1539 PutRawBytes(&c, 1);
1540}
1541
1542
1543
1544void
1545POutPersist::PutBytes(void const* ptr, size_t bytes)
1546{
1547 PutArrayTag(1, bytes, PPS_DATATYPE_CHAR);
1548 PutRawBytes(ptr, bytes);
1549}
1550
1551void
1552POutPersist::PutR4 (r_4 val)
1553{
1554 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_FLOAT);
1555
1556 if (bigEndian != IS_BIG_ENDIAN)
1557 bswap4(&val);
1558
1559 PutRawBytes(&val, sizeof(r_4));
1560}
1561
1562void
1563POutPersist::PutR4s (r_4 const* tab, size_t n)
1564{
1565 PutArrayTag(4, n, PPS_DATATYPE_FLOAT);
1566
1567 if (bigEndian == IS_BIG_ENDIAN) {
1568 PutRawBytes(tab, n*sizeof(r_4));
1569 } else {
1570 for (unsigned int i=0; i<n; i++) {
1571 r_4 val = tab[i];
1572 bswap4(&val);
1573 PutRawBytes(&val, sizeof(r_4));
1574 }
1575 }
1576}
1577
1578void
1579POutPersist::PutR8 (r_8 val)
1580{
1581 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_FLOAT);
1582
1583 if (bigEndian != IS_BIG_ENDIAN)
1584 bswap8(&val);
1585
1586 PutRawBytes(&val, sizeof(r_8));
1587}
1588
1589void
1590POutPersist::PutR8s (r_8 const* tab, size_t n)
1591{
1592 PutArrayTag(8, n, PPS_DATATYPE_FLOAT);
1593
1594 if (bigEndian == IS_BIG_ENDIAN) {
1595 PutRawBytes(tab, n*sizeof(r_8));
1596 } else {
1597 for (unsigned int i=0; i<n; i++) {
1598 r_8 val = tab[i];
1599 bswap8(&val);
1600 PutRawBytes(&val, sizeof(r_8));
1601 }
1602 }
1603}
1604
1605void
1606POutPersist::PutI1 (int_1 val)
1607{
1608 PutRawUByte(PPS_SIMPLE + 1 + PPS_DATATYPE_INTEGER);
1609 PutRawBytes(&val, sizeof(int_1));
1610}
1611
1612void
1613POutPersist::PutI1s (int_1 const* tab, size_t n)
1614{
1615 PutArrayTag(1, n, PPS_DATATYPE_INTEGER);
1616 PutRawBytes(tab, n*sizeof(int_1));
1617}
1618
1619void
1620POutPersist::PutU1 (uint_1 val)
1621{
1622 PutRawUByte(PPS_SIMPLE + 1 + PPS_DATATYPE_UNSIGNED);
1623 PutRawBytes(&val, sizeof(uint_1));
1624}
1625
1626void
1627POutPersist::PutU1s (uint_1 const* tab, size_t n)
1628{
1629 PutArrayTag(1, n, PPS_DATATYPE_UNSIGNED);
1630 PutRawBytes(tab, n*sizeof(uint_1));
1631}
1632
1633void
1634POutPersist::PutI2 (int_2 val)
1635{
1636 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_INTEGER);
1637
1638 if (bigEndian != IS_BIG_ENDIAN)
1639 bswap2(&val);
1640
1641 PutRawBytes(&val, sizeof(int_2));
1642}
1643
1644void
1645POutPersist::PutI2s (int_2 const* tab, size_t n)
1646{
1647 PutArrayTag(2, n, PPS_DATATYPE_INTEGER);
1648
1649 if (bigEndian == IS_BIG_ENDIAN) {
1650 PutRawBytes(tab, n*sizeof(int_2));
1651 } else {
1652 for (unsigned int i=0; i<n; i++) {
1653 int_2 val = tab[i];
1654 bswap2(&val);
1655 PutRawBytes(&val, sizeof(int_2));
1656 }
1657 }
1658}
1659
1660void
1661POutPersist::PutU2 (uint_2 val)
1662{
1663 PutRawUByte(PPS_SIMPLE + 2 + PPS_DATATYPE_UNSIGNED);
1664
1665 if (bigEndian != IS_BIG_ENDIAN)
1666 bswap2(&val);
1667
1668 PutRawBytes(&val, sizeof(uint_2));
1669}
1670
1671void
1672POutPersist::PutU2s (uint_2 const* tab, size_t n)
1673{
1674 PutArrayTag(2, n, PPS_DATATYPE_UNSIGNED);
1675
1676 if (bigEndian == IS_BIG_ENDIAN) {
1677 PutRawBytes(tab, n*sizeof(uint_2));
1678 } else {
1679 for (unsigned int i=0; i<n; i++) {
1680 uint_2 val = tab[i];
1681 bswap2(&val);
1682 PutRawBytes(&val, sizeof(uint_2));
1683 }
1684 }
1685}
1686
1687void
1688POutPersist::PutI4 (int_4 val)
1689{
1690 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_INTEGER);
1691
1692 if (bigEndian != IS_BIG_ENDIAN)
1693 bswap4(&val);
1694
1695 PutRawBytes(&val, sizeof(int_4));
1696}
1697
1698void
1699POutPersist::PutI4s (int_4 const* tab, size_t n)
1700{
1701 PutArrayTag(4, n, PPS_DATATYPE_INTEGER);
1702
1703 if (bigEndian == IS_BIG_ENDIAN) {
1704 PutRawBytes(tab, n*sizeof(int_4));
1705 } else {
1706 for (unsigned int i=0; i<n; i++) {
1707 int_4 val = tab[i];
1708 bswap4(&val);
1709 PutRawBytes(&val, sizeof(int_4));
1710 }
1711 }
1712}
1713
1714void
1715POutPersist::PutU4 (uint_4 val)
1716{
1717 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_UNSIGNED);
1718
1719 if (bigEndian != IS_BIG_ENDIAN)
1720 bswap4(&val);
1721
1722 PutRawBytes(&val, sizeof(uint_4));
1723}
1724
1725void
1726POutPersist::PutU4s (uint_4 const* tab, size_t n)
1727{
1728 PutArrayTag(4, n, PPS_DATATYPE_UNSIGNED);
1729
1730 if (bigEndian == IS_BIG_ENDIAN) {
1731 PutRawBytes(tab, n*sizeof(uint_4));
1732 } else {
1733 for (unsigned int i=0; i<n; i++) {
1734 uint_4 val = tab[i];
1735 bswap4(&val);
1736 PutRawBytes(&val, sizeof(uint_4));
1737 }
1738 }
1739}
1740
1741void
1742POutPersist::PutI8 (int_8 val)
1743{
1744 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_INTEGER);
1745
1746 if (bigEndian != IS_BIG_ENDIAN)
1747 bswap8(&val);
1748
1749 PutRawBytes(&val, sizeof(int_8));
1750}
1751
1752void
1753POutPersist::PutI8s (int_8 const* tab, size_t n)
1754{
1755 PutArrayTag(8, n, PPS_DATATYPE_INTEGER);
1756
1757 if (bigEndian == IS_BIG_ENDIAN) {
1758 PutRawBytes(tab, n*sizeof(int_8));
1759 } else {
1760 for (unsigned int i=0; i<n; i++) {
1761 int_8 val = tab[i];
1762 bswap8(&val);
1763 PutRawBytes(&val, sizeof(int_8));
1764 }
1765 }
1766}
1767
1768void
1769POutPersist::PutU8 (uint_8 val)
1770{
1771 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_UNSIGNED);
1772
1773 if (bigEndian != IS_BIG_ENDIAN)
1774 bswap8(&val);
1775
1776 PutRawBytes(&val, sizeof(uint_8));
1777}
1778
1779void
1780POutPersist::PutU8s (uint_8 const* tab, size_t n)
1781{
1782 PutArrayTag(8, n, PPS_DATATYPE_UNSIGNED);
1783
1784 if (bigEndian == IS_BIG_ENDIAN) {
1785 PutRawBytes(tab, n*sizeof(uint_8));
1786 } else {
1787 for (unsigned int i=0; i<n; i++) {
1788 uint_8 val = tab[i];
1789 bswap8(&val);
1790 PutRawBytes(&val, sizeof(uint_8));
1791 }
1792 }
1793}
1794
1795void
1796POutPersist::PutStr(string const& str)
1797{
1798 PutRawUByte(PPS_STRING);
1799 PutRawI4(str.length());
1800 PutRawBytes(str.c_str(), str.length());
1801}
1802
1803void
1804POutPersist::PutLine(char const* ptr, size_t len)
1805{
1806 string str = ptr;
1807 PutStr(str);
1808}
1809
1810
1811void
1812POutPersist::PutZ4 (complex<r_4> val)
1813{
1814 PutRawUByte(PPS_SIMPLE + 4 + PPS_DATATYPE_COMPLEX);
1815 r_4 reim[2];
1816 reim[0] = val.real();
1817 reim[1] = val.imag();
1818 if (bigEndian != IS_BIG_ENDIAN) {
1819 bswap4(reim);
1820 bswap4(reim+1);
1821 }
1822 PutRawBytes(reim, 2*sizeof(r_4));
1823}
1824
1825void
1826POutPersist::PutZ4s (complex<r_4> const* tab, size_t n)
1827{
1828 PutArrayTag(4, n, PPS_DATATYPE_COMPLEX);
1829
1830 if (bigEndian == IS_BIG_ENDIAN) {
1831 PutRawBytes(tab, n*2*sizeof(r_4));
1832 } else {
1833 for (unsigned int i=0; i<n; i++) {
1834 r_4 reim[2];
1835 reim[0] = tab[i].real();
1836 reim[1] = tab[i].imag();
1837 bswap4(reim);
1838 bswap4(reim+1);
1839 PutRawBytes(reim, 2*sizeof(r_4));
1840 }
1841 }
1842}
1843
1844void
1845POutPersist::PutZ8 (complex<r_8> val)
1846{
1847 PutRawUByte(PPS_SIMPLE + 8 + PPS_DATATYPE_COMPLEX);
1848 r_8 reim[2];
1849 reim[0] = val.real();
1850 reim[1] = val.imag();
1851 if (bigEndian != IS_BIG_ENDIAN) {
1852 bswap8(reim);
1853 bswap8(reim+1);
1854 }
1855 PutRawBytes(reim, 2*sizeof(r_8));
1856}
1857
1858void
1859POutPersist::PutZ8s (complex<r_8> const* tab, size_t n)
1860{
1861 PutArrayTag(8, n, PPS_DATATYPE_COMPLEX);
1862
1863 if (bigEndian == IS_BIG_ENDIAN) {
1864 PutRawBytes(tab, n*2*sizeof(r_8));
1865 } else {
1866 for (unsigned int i=0; i<n; i++) {
1867 r_8 reim[2];
1868 reim[0] = tab[i].real();
1869 reim[1] = tab[i].imag();
1870 bswap8(reim);
1871 bswap8(reim+1);
1872 PutRawBytes(reim, 2*sizeof(r_8));
1873 }
1874 }
1875}
1876
1877void
1878POutPersist::PutPosTagTable(int_8 const * ptab, size_t sz)
1879{
1880 PutRawUByte(PPS_POSTAG_TABLE);
1881 int_4 tsz = sz;
1882 PutRawI4(tsz);
1883 for(int kk=0; kk<tsz; kk++)
1884 PutRawI8(ptab[kk]);
1885 return;
1886}
1887
1888void
1889POutPersist::PutPosTagTable(vector<int_8> const& ptab)
1890{
1891 PutRawUByte(PPS_POSTAG_TABLE);
1892 int_4 tsz = ptab.size();
1893 PutRawI4(tsz);
1894 for(int kk=0; kk<tsz; kk++)
1895 PutRawI8(ptab[kk]);
1896 return;
1897}
1898
1899void
1900POutPersist::PutObject(AnyDataObj & o)
1901{
1902 ClassCreatorFunc f = FindCreatorFunc(getDataObjClassId(o));
1903 if (!f)
1904 throw NotFoundExc("PInPersist::PutObject() class not registered");
1905 PPersist* ppo = f();
1906 ppo->SetDataObj(o);
1907 PutPPObject(ppo);
1908}
1909
1910void
1911POutPersist::PutObject(AnyDataObj & o, string tagname)
1912{
1913 WriteNameTag(tagname);
1914 PutObject(o);
1915}
1916
1917
1918void
1919POutPersist::PutPPObject(PPersist const* obj)
1920{
1921 if (serializeNullAndRepeat(obj)) return; // NULL object or already written in stream
1922
1923 // We have to write the object
1924 uint_8 oid = assignObjectId(obj); // We assing a PPS Object Id
1925 PutRawUByte(PPS_OBJECT); // We write the Object Tag
1926 PutRawU8(getPPClassId(*obj)); // Writing the PPersist ClassId
1927 PutRawU8(oid); // Write the PPS Object Id
1928 obj->WriteSelf(*this);
1929 PutRawUByte(PPS_ENDOBJECT); // We write the End-Of-Object Tag
1930 PutRawU8(oid); // and again its PPS Object Id
1931}
1932
1933bool
1934POutPersist::serializeNullAndRepeat(PPersist const* x)
1935{
1936 if (x == NULL) {
1937 PutRawUByte(PPS_NULL);
1938 return true;
1939 }
1940
1941 int_8 pos;
1942 uint_8 id = findObjectId(x, pos);
1943 if (id > 0) {
1944 PutRawUByte(PPS_REFERENCE);
1945 PutRawU8(id); // Writing the corresponding object Id
1946 PutRawI8(pos); // The original object position
1947 return true;
1948 }
1949
1950 return false; // Object have to be written in stream ...
1951}
1952
1953uint_8
1954POutPersist::assignObjectId(PPersist const* x)
1955{
1956 pps_OId += 16; // We keep the three first bytes for future usage
1957 // Bit 1 non zero -> Object can be referenced
1958 uint_8 id = pps_OId;
1959 uint_8 mid = x->getMemOId();
1960 if (mid > 0) {
1961 int_8 pos;
1962 if (findObjectId(x,pos) > 0)
1963 throw PError("POutPersist::assignObjectId() Error - Already serialized object ! ");
1964 id += 1; // Bit 1 non zero -> Object can be referenced
1965 objreftag rt;
1966 rt.ppsoid = id;
1967 rt.ppspos = s->tellp();
1968 objList[mid] = rt;
1969 }
1970 return id;
1971}
1972
1973uint_8
1974POutPersist::findObjectId(PPersist const* x, int_8 & pos)
1975{
1976 pos = -1;
1977 uint_8 mid = x->getMemOId();
1978 if (mid == 0) return(0);
1979 ObjList::iterator i = objList.find(mid);
1980 if (i == objList.end()) return 0;
1981 pos = (*i).second.ppspos;
1982 return (*i).second.ppsoid;
1983}
1984
1985
Note: See TracBrowser for help on using the repository browser.