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

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

Portage sous MacOSX 10.2 - g++ 3.1 (Pb avec classe SophyaInitiator statique, lecture last byte ds istream) , Reza 12/09/2003

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