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

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

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

File size: 17.2 KB
Line 
1// This may look like C code, but it is really -*- C++ -*-
2
3#ifndef PPERSIST_H_SEEN
4#define PPERSIST_H_SEEN
5
6// Flat file persistance, similar to Java serialization
7//
8// E. Aubourg CEA DAPNIA/SPP 1999
9// R. Ansari LAL IN2P3/CNRS 03/2000
10
11
12#include "machdefs.h"
13#include "pexceptions.h"
14#include "gnumd5.h"
15#include "rawstream.h"
16
17
18#include <time.h>
19
20#include <complex>
21#include <string>
22#include <map>
23#include <vector>
24#include <typeinfo>
25
26
27// Classe de base pour les objets qui peuvent devenir PPersist
28
29namespace SOPHYA {
30
31 class AnyDataObj;
32
33 class PIOPersist;
34 class PInPersist;
35 class POutPersist;
36 class PPersist;
37
38//! Persistent (delegate or mixin) base class
39 class PPersist {
40 public:
41 virtual ~PPersist() {}
42
43 void Write(string const& fn) const;
44 void Read(string const& fn);
45
46 virtual void Write(POutPersist&) const;
47 void Read(PInPersist& s); // Reads the type tag and the object
48 void Write(POutPersist&, string const& tag) const;
49 void ReadAtTag(PInPersist& s, string const& tag);
50
51 virtual AnyDataObj* DataObj()=0; // Retourne l'objet reel
52 virtual void SetDataObj(AnyDataObj &)=0;
53
54 virtual uint_8 getMemOId() const ; // Renvoie l'identificateur de l'objet - par defaut=0
55 // Ces deux methodes doivent etre redefinies si getMemOId() renvoie non nul (>0)
56 virtual void ShareDataReference(PPersist &);
57 virtual PPersist* CloneSharedReference();
58 // doit etre surcharge pour renvoyer un mem-oid correct
59 protected:
60 virtual void ReadSelf(PInPersist&)=0;
61 virtual void WriteSelf(POutPersist&) const=0;
62
63 friend class PInPersist;
64 friend class POutPersist;
65 };
66
67
68
69//! Ancestor for PInPersist and POutPersist PPF streams.
70// Handles (statically) the registration of classes.
71
72 class PIOPersist {
73 public:
74 enum {PPS_NATIVE = -1, PPS_LITTLE_ENDIAN = 0, PPS_BIG_ENDIAN = 1};
75 typedef PPersist* (*ClassCreatorFunc)();
76
77 static void RegisterPPHandlerClass(uint_8 classId, string ppclass_name, ClassCreatorFunc f);
78 static void RegisterDataObjClass(uint_8 classId, string class_name);
79
80 static ClassCreatorFunc FindCreatorFunc(uint_8 classId);
81
82 static string getPPClassName(uint_8 classId);
83 static uint_8 getPPClassId(string const & typ_name);
84 static uint_8 getPPClassId(PPersist const & ppo);
85 static string getDataObjClassName(uint_8 classId);
86 static uint_8 getDataObjClassId(string const & typ_name);
87 static uint_8 getDataObjClassId(AnyDataObj const & o);
88
89 static uint_8 Hash(string const& typname);
90 static MD5_CONTEXT ctx;
91
92 static void Initialize(); // Pour initialiser classList
93
94 int Version() {return version;} // PIn/OutPersist version number
95 string FileName() { return filename; } // Retourne le nom de fichier
96
97 private:
98
99 typedef map<uint_8, ClassCreatorFunc, less<uint_8> > ClassList;
100 // Pas de createur appele pour objets statiques sur Linux - $CHECK$ Reza 26/04/99
101 static ClassList * ppclassList; // PPersist class list
102 static map<string, uint_8> * ppclassNameList; // PPersist classId = f(PPersistClassName)
103 static map<string, uint_8> * dobjclassNameList; // PPersist classId = f(DataObjClassName)
104
105 protected:
106
107 enum {PPS_NULL = 0, // this is a null object
108 PPS_STRING = 1, // string, length (4b) + data
109 PPS_OBJECT = 2, // classId, data...
110 PPS_REFERENCE = 3, // objectId
111 PPS_NAMETAG_TABLE = 4, // Name tag table (Written at the end of file/stream)
112 PPS_EOF = 5, // Just before tag infomation, offset to PPS_TAG
113 PPS_ENDOBJECT = 6, // marks the end of a given object information
114 PPS_NAMETAG_MARK = 7, // To have a name tag, position marker in a file
115 PPS_POSTAG_MARK = 8, // Position tag mark + 8 bytes (=stream position)
116 PPS_POSTAG_TABLE = 9, // Position tag table + 8 bytes (=stream position)
117 PPS_SIMPLE = 16, // 16 + number of bytes, up to 8 bytes
118 PPS_SIMPLE_ARRAY4 = 32, // 32 + number of bytes, up to 8 bytes, then 4 bytes of length
119 PPS_SIMPLE_ARRAY8 = 48 // 48 + number of bytes, up to 8 bytes, then 8 bytes of length
120 };
121 // The following values are used with PPS_SIMPLE and PPS_SIMPLE_ARRAY (Using OR)
122 enum {PPS_DATATYPE_CHAR = 0, // 0 : DataType=character
123 PPS_DATATYPE_FLOAT = 64, // 64 : DataType=float
124 PPS_DATATYPE_COMPLEX = 65, // 65 : DataType=complex
125 PPS_DATATYPE_INTEGER = 128, // 128 :DataType=integer
126 PPS_DATATYPE_UNSIGNED = 192 // 192 :DataType=Unsigned integer
127 };
128
129 map<string, int_8> tags;
130 string filename;
131 int version; // PPersist(In/Out) version
132 };
133
134
135// TBD : use hash tables instead of maps. Check hashtbl status in STL.
136
137//! Input stream for PPersit objects.
138 class PInPersist : public PIOPersist {
139 public:
140 PInPersist(string const& flnm, bool scan=true);
141 ~PInPersist();
142
143 // Gestion des tags
144 bool GotoPositionTag(int_8 pos);
145 bool GotoNameTag(string const& name);
146 int NbNameTags();
147 bool GotoNameTagNum(int itag); // 0..NbTags-1
148 string GetTagName(int itag); // 0..NbTags-1
149 string GetTagClassName(int itag); // 0..NbTags-1
150 vector<string> const & GetNameTags();
151
152 // Saut jusqu'au prochain objet
153 bool SkipToNextObject();
154
155 // Lecture donnees de base et tableaux de donnees de base
156 // Basic data type (and corresponding arrays) reading
157 void GetByte (char& c);
158 void GetBytes(void* ptr, size_t bytes);
159 void GetR4 (r_4&);
160 void GetR4s (r_4*, size_t);
161 void GetR8 (r_8&);
162 void GetR8s (r_8*, size_t);
163 void GetI1 (int_1&);
164 void GetI1s (int_1*, size_t);
165 void GetU1 (uint_1&);
166 void GetU1s (uint_1*, size_t);
167 void GetI2 (int_2&);
168 void GetI2s (int_2*, size_t);
169 void GetU2 (uint_2&);
170 void GetU2s (uint_2*, size_t);
171 void GetI4 (int_4&);
172 void GetI4s (int_4*, size_t);
173 void GetU4 (uint_4&);
174 void GetU4s (uint_4*, size_t);
175 void GetI8 (int_8&);
176 void GetI8s (int_8*, size_t);
177 void GetU8 (uint_8&);
178 void GetU8s (uint_8*, size_t);
179 void GetLine (char* ptr, size_t len);
180 void GetStr (string&);
181 void GetZ4 (complex<r_4> &);
182 void GetZ4s (complex<r_4> *, size_t);
183 void GetZ8 (complex<r_8> &);
184 void GetZ8s (complex<r_8> *, size_t);
185
186 inline void Get(char& c) {GetByte(c);}
187 inline void Get(r_4& x) {GetR4(x);}
188 inline void Get(r_8& x) {GetR8(x);}
189 inline void Get(uint_1& x) {GetU1(x);}
190 inline void Get(int_1& x) {GetI1(x);}
191 inline void Get(uint_2& x) {GetU2(x);}
192 inline void Get(int_2& x) {GetI2(x);}
193 inline void Get(uint_4& x) {GetU4(x);}
194 inline void Get(int_4& x) {GetI4(x);}
195 inline void Get(uint_8& x) {GetU8(x);}
196 inline void Get(int_8& x) {GetI8(x);}
197 inline void Get(complex<r_4> & x) {GetZ4(x);}
198 inline void Get(complex<r_8> & x) {GetZ8(x);}
199
200 inline void Get(r_4* x, size_t n) {GetR4s(x,n);}
201 inline void Get(r_8* x, size_t n) {GetR8s(x,n);}
202 inline void Get(uint_1* x, size_t n) {GetU1s(x,n);}
203 inline void Get(int_1* x, size_t n) {GetI1s(x,n);}
204 inline void Get(uint_2* x, size_t n) {GetU2s(x,n);}
205 inline void Get(int_2* x, size_t n) {GetI2s(x,n);}
206 inline void Get(uint_4* x, size_t n) {GetU4s(x,n);}
207 inline void Get(int_4* x, size_t n) {GetI4s(x,n);}
208 inline void Get(uint_8* x, size_t n) {GetU8s(x,n);}
209 inline void Get(int_8* x, size_t n) {GetI8s(x,n);}
210 inline void Get(string& x) {GetStr(x);}
211 inline void Get(complex<r_4> * x, size_t n) { GetZ4s(x, n); }
212 inline void Get(complex<r_8> * x, size_t n) { GetZ8s(x, n); }
213
214 // Reading a list (table) of position tags
215 void GetPosTagTable(int_8*, size_t);
216 void GetPosTagTable(vector<int_8>&);
217
218 // Object Reading
219 PPersist* ReadObject();
220 void GetObject(AnyDataObj & o);
221 void GetObject(AnyDataObj & o, string tagname);
222 PPersist* GetPPObject(AnyDataObj * po=NULL);
223
224 time_t CreationDate() { return creationdate; }
225 string CreationDateStr();
226
227 void AnalyseTags(int lev=0); // List (all or some) tags ...
228
229 // Reza 03/2000
230 // Methodes qui pourraient etre protected, mais doivent etre utilisables par PPersist
231 void ReadReference(PPersist & ppo); // Fill the ppo object from the reference tag
232 PPersist * ReadReference(); // Creates object from the reference tag
233 void KeepOId(uint_8 oid, PPersist & ppo); // Keeps the ppo in the objList
234
235 protected:
236 void CheckTag (short datasz, short datatype);
237 void CheckArrayTag(short datasz, size_t sz, short datatype);
238 void GetTypeTag (unsigned char& c);
239 void GetRawByte (char& c);
240 void GetRawUByte (unsigned char& c);
241 void GetRawBytes(void* ptr, size_t bytes);
242 void GetRawI2 (int_2&);
243 void GetRawI4 (int_4&);
244 void GetRawI8 (int_8&);
245 void GetRawU8 (uint_8&);
246
247 void Scan();
248
249 RawInOutStream* s;
250
251 bool bigEndian;
252
253 time_t creationdate;
254
255 // already read objects
256 typedef map<uint_8, PPersist * > ObjList;
257 ObjList objList;
258 // Si on a fait une lecture non sequentielle -> seqread = false
259 bool seqread;
260 friend class PPersist;
261 };
262
263//! Output stream for PPersit objects.
264 class POutPersist : public PIOPersist {
265 public:
266 POutPersist(string const& flnm, int endianness = PPS_NATIVE);
267 ~POutPersist();
268
269 // Ecriture de tags
270 int_8 WritePositionTag();
271 void WriteNameTag(string const& name);
272 inline void WriteTag(string const& name) { WriteNameTag(name); }
273
274 void PutByte (char c);
275 void PutBytes(void const* ptr, size_t bytes);
276 void PutR4 (r_4);
277 void PutR4s (r_4 const*, size_t);
278 void PutR8 (r_8);
279 void PutR8s (r_8 const*, size_t);
280 void PutI1 (int_1);
281 void PutI1s (int_1 const*, size_t);
282 void PutU1 (uint_1);
283 void PutU1s (uint_1 const*, size_t);
284 void PutI2 (int_2);
285 void PutI2s (int_2 const*, size_t);
286 void PutU2 (uint_2);
287 void PutU2s (uint_2 const*, size_t);
288 void PutI4 (int_4);
289 void PutI4s (int_4 const*, size_t);
290 void PutU4 (uint_4);
291 void PutU4s (uint_4 const*, size_t);
292 void PutI8 (int_8);
293 void PutI8s (int_8 const*, size_t);
294 void PutU8 (uint_8);
295 void PutU8s (uint_8 const*, size_t);
296 void PutLine (char const* ptr, size_t len=0); // deprecated ?
297 void PutStr (string const&);
298 void PutZ4 (complex<r_4>);
299 void PutZ4s (complex<r_4> const*, size_t);
300 void PutZ8 (complex<r_8>);
301 void PutZ8s (complex<r_8> const*, size_t);
302
303
304 void Put(char c) {PutByte(c);}
305 void Put(r_4 x) {PutR4(x);}
306 void Put(r_8 x) {PutR8(x);}
307 void Put(complex<r_4> x) {PutZ4(x);}
308 void Put(complex<r_8> x) {PutZ8(x);}
309 void Put(uint_1 x) {PutU1(x);}
310 void Put(int_1 x) {PutI1(x);}
311 void Put(uint_2 x) {PutU2(x);}
312 void Put(int_2 x) {PutI2(x);}
313 void Put(uint_4 x) {PutU4(x);}
314 void Put(int_4 x) {PutI4(x);}
315 void Put(uint_8 x) {PutU8(x);}
316 void Put(int_8 x) {PutI8(x);}
317 void Put(r_4 const* x, size_t n) {PutR4s(x,n);}
318 void Put(r_8 const* x, size_t n) {PutR8s(x,n);}
319 void Put(complex<r_4> const* x, size_t n) {PutZ4s(x,n);}
320 void Put(complex<r_8> const* x, size_t n) {PutZ8s(x,n);}
321 void Put(uint_1 const* x, size_t n) {PutU1s(x,n);}
322 void Put(int_1 const* x, size_t n) {PutI1s(x,n);}
323 void Put(uint_2 const* x, size_t n) {PutU2s(x,n);}
324 void Put(int_2 const* x, size_t n) {PutI2s(x,n);}
325 void Put(uint_4 const* x, size_t n) {PutU4s(x,n);}
326 void Put(int_4 const* x, size_t n) {PutI4s(x,n);}
327 void Put(uint_8 const* x, size_t n) {PutU8s(x,n);}
328 void Put(int_8 const* x, size_t n) {PutI8s(x,n);}
329 void Put(string const& s) {PutStr(s);}
330 void Put(PPersist const* x) {PutPPObject(x);}
331
332 // Writing a list of position tag table
333 void PutPosTagTable(int_8 const *, size_t);
334 void PutPosTagTable(vector<int_8> const&);
335
336 // Objet Write - Ecriture des objets
337 void PutPPObject (PPersist const*); // Like doing Write(stream) on PPersist object
338
339 void PutObject(AnyDataObj & o); // Creates the corresponding PPersist Object and call Write()
340 void PutObject(AnyDataObj & o, string tagname);
341
342
343 protected:
344 RawInOutStream* s;
345 bool bigEndian;
346
347 void PutArrayTag(short datasz, size_t sz, short datatype);
348 void PutRawByte (char);
349 void PutRawUByte (unsigned char);
350 void PutRawI2 (int_2);
351 void PutRawI4 (int_4);
352 void PutRawI8 (int_8);
353 void PutRawU8 (uint_8);
354 void PutRawBytes(void const* ptr, size_t bytes);
355 bool serializeNullAndRepeat(PPersist const* x);
356 uint_8 findObjectId(PPersist const* x, int_8 & pos);
357 uint_8 assignObjectId(PPersist const* x);
358
359 // objreftag contains the assigned POutStream Object Id and the stream position
360 // of the original written object
361 typedef struct { uint_8 ppsoid; int_8 ppspos; } objreftag;
362 // already serialized objects are kept in a map as a function of the Objects memory Id
363 typedef map<uint_8, objreftag, less<uint_8> > ObjList;
364 ObjList objList;
365 uint_8 pps_OId; // PPS Object Id
366 };
367
368
369// Le macro suivant permettent de simplifier la declaration
370// des operateurs >> << sur les POutPersist et PInPersist
371#define RAWPERSISTIO(_Type_,_xtyp_) \
372 inline POutPersist& operator << (POutPersist& c, _Type_ const& data) \
373 { \
374 c.Put##_xtyp_(data); \
375 return c; \
376 } \
377 \
378 inline PInPersist& operator >> (PInPersist& c, _Type_& data) \
379 { \
380 c.Get##_xtyp_(data); \
381 return c; \
382 }
383
384// On utilise le macro RAWPERSISTIO pour declarer POutPersist << et PInPersist >>
385// pour les types de base r_4 r_8 int_4 int_8 ...
386 RAWPERSISTIO(int_4,I4);
387 RAWPERSISTIO(uint_4,U4);
388 RAWPERSISTIO(int_2,I2);
389 RAWPERSISTIO(uint_2,U2);
390 RAWPERSISTIO(char,Byte);
391 RAWPERSISTIO(r_4,R4);
392 RAWPERSISTIO(r_8,R8);
393 RAWPERSISTIO(complex<r_4>,Z4);
394 RAWPERSISTIO(complex<r_8>,Z8);
395 RAWPERSISTIO(string,Str);
396
397#if 0
398#define STRUCTPERSISTIO(_Type_, _field_, _size_) \
399 inline POutPersist& operator << (POutPersist& c, _Type_ const& data) \
400 { \
401 c.PutBytes(&data._field_, _size_); \
402 return c; \
403 } \
404 \
405 inline PInPersist& operator >> (PInPersist& c, _Type_& data) \
406 { \
407 c.GetBytes(&data._field_, _size_); \
408 return c; \
409 }
410
411#endif
412
413
414// --- Cela risque d'etre dangereux --- On le laisse au niveau des DataObj
415// Reza 24/3/2000
416// inline POutPersist& operator << (POutPersist& c, PPersist const& obj)
417// {
418// obj.Write(c);
419// return c;
420// }
421
422// inline PInPersist& operator >> (PInPersist& c, PPersist& obj)
423// {
424// obj.Read(c);
425// return c;
426// }
427
428 // Utility class to
429 // - compute the class ID from a MD5 hash of the class name
430 // - register classes with PIOPersist, through PPRegister macro
431
432//! template class for handling the PPersist registration mechanism.
433 template <class T>
434 class PPersistRegistrar {
435 public:
436 static PPersist* Create() {return new T();}
437 static void Register(string id) { PIOPersist::RegisterPPHandlerClass(Hash(id), typeid(T).name(), Create); }
438 static uint_8 Hash(string id) {
439 return PIOPersist::Hash(id);
440 }
441 };
442
443#define PPRegister(className) PPersistRegistrar<className>::Register(#className);
444#define DObjRegister(ppclassName, className) PIOPersist::RegisterDataObjClass(PIOPersist::Hash(#ppclassName), typeid(className).name());
445
446} // namespace
447
448#endif
Note: See TracBrowser for help on using the repository browser.