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

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

Correction commentaires - Reza 06/04/2000

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