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

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

bug swap md5

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