blob: 3874ad585caf2d593675e1477c7c1c97badc99ef [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * The GNU Common C++ persistance engine by Daniel Silverstone.
20 * @file ucommon/persist.h
21 */
22
23#if defined(OLD_STDCPP) || defined(NEW_STDCPP)
24#if !defined(_MSC_VER) || _MSC_VER >= 1400
25#ifndef _UCOMMON_PERSIST_H_
26#define _UCOMMON_PERSIST_H_
27
28#ifndef _UCOMMON_PLATFORM_H_
29#include <ucommon/platform.h>
30#endif
31
32#include <iostream>
33#include <string>
34#include <vector>
35#include <deque>
36#include <map>
37
38NAMESPACE_UCOMMON
39#define NS_PREFIX ucc::
40
41// This typedef allows us to declare NewPersistObjectFunction now
42typedef class PersistObject* (*NewPersistObjectFunction) (void);
43
44class __EXPORT PersistException
45{
46public:
47 PersistException(const std::string& reason);
48 const std::string& getString() const;
49
50 virtual ~PersistException() throw();
51
52protected:
53 std::string _what;
54};
55
56/**
57 * Type manager for persistence engine.
58 * This class manages the types for generation of the persistent objects.
59 * Its data structures are managed automatically by the system. They are
60 * implicitly filled by the constructors who declare classes to the system.
61 *
62 * @author Daniel Silverstone
63 */
64class __EXPORT TypeManager
65{
66public:
67 /**
68 * This manages a registration to the typemanager - attempting to
69 * remove problems with the optimizers
70 */
71 class registration
72 {
73 public:
74 registration(const char* name, NewPersistObjectFunction func);
75 virtual ~registration();
76 private:
77 std::string myName;
78 };
79
80 /**
81 * This adds a new construction function to the type manager
82 */
83 static void add(const char* name, NewPersistObjectFunction construction);
84
85 /**
86 * And this one removes a type from the managers lists
87 */
88 static void remove(const char* name);
89
90 /**
91 * This function creates a new object of the required type and
92 * returns a pointer to it. NULL is returned if we couldn't find
93 * the type
94 */
95 static PersistObject* createInstanceOf(const char* name);
96
97 typedef std::map<std::string,NewPersistObjectFunction> StringFunctionMap;
98};
99
100/*
101 * The following defines are used to declare and define the relevant code
102 * to allow a class to use the Persistence::Engine code.
103 */
104
105#define DECLARE_PERSISTENCE(ClassType) \
106 public: \
107 friend NS_PREFIX PersistEngine& operator>>( NS_PREFIX PersistEngine& ar, ClassType *&ob); \
108 friend NS_PREFIX PersistEngine& operator<<( NS_PREFIX PersistEngine& ar, ClassType const &ob); \
109 friend NS_PREFIX PersistObject *createNew##ClassType(); \
110 virtual const char* getPersistenceID() const; \
111 static NS_PREFIX TypeManager::Registration registrationFor##ClassType;
112
113#define IMPLEMENT_PERSISTENCE(ClassType, FullyQualifiedName) \
114 NS_PREFIX PersistObject *createNew##ClassType() { return new ClassType; } \
115 const char* ClassType::getPersistenceID() const {return FullyQualifiedName;} \
116 NS_PREFIX PersistEngine& operator>>(NS_PREFIX PersistEngine& ar, ClassType &ob) \
117 { ar >> (NS_PREFIX PersistObject &) ob; return ar; } \
118 NS_PREFIX PersistEngine& operator>>(NS_PREFIX PersistEngine& ar, ClassType *&ob) \
119 { ar >> (NS_PREFIX PersistObject *&) ob; return ar; } \
120 NS_PREFIX PersistEngine& operator<<(NS_PREFIX PersistEngine& ar, ClassType const &ob) \
121 { ar << (NS_PREFIX PersistObject const *)&ob; return ar; } \
122 NS_PREFIX TypeManager::Registration \
123 ClassType::registrationFor##ClassType(FullyQualifiedName, \
124 createNew##ClassType);
125
126class PersistEngine;
127
128/**
129 * PersistObject
130 *
131 * Base class for classes that will be persistent. This object is the base
132 * for all Persistent data which is not natively serialized by the
133 * persistence::engine
134 *
135 * It registers itself with the persistence::TypeManager
136 * using a global constructor function. A matching deregister call
137 * is made in a global destructor, to allow DLL's to use the
138 * persistence::engine in a main executable.
139 *
140 * Persistable objects must never maintain bad pointers. If a pointer
141 * doesn't point to something valid, it must be NULL. This is so
142 * the persistence engine knows whether to allocate memory for an object
143 * or whether the memory has been pre-allocated.
144 *
145 * @author Daniel Silverstone
146 */
147class __EXPORT PersistObject
148{
149public:
150 /**
151 * This constructor is used in serialization processes.
152 * It is called in CreateNewInstance in order to create
153 * an instance of the class to have Read() called on it.
154 */
155 PersistObject();
156
157 /**
158 * Default destructor
159 */
160 virtual ~PersistObject();
161
162 /**
163 * This returns the ID of the persistent object (Its type)
164 */
165 virtual const char* getPersistenceID() const;
166
167 /**
168 * This method is used to write to the Persistence::Engine
169 * It is not equivalent to the << operator as it writes only the data
170 * and not the object type etc.
171 */
172 virtual bool write(PersistEngine& archive) const;
173
174 /**
175 * This method is used to read from a Persistence::Engine
176 * It is not equivalent to the >> operator as it does no
177 * typesafety or anything.
178 */
179 virtual bool read(PersistEngine& archive);
180};
181
182/**
183 * Stream serialization of persistent classes.
184 * This class constructs on a standard C++ STL stream and then
185 * operates in the mode specified. The stream passed into the
186 * constructor must be a binary mode to function properly.
187 *
188 * @author Daniel Silverstone
189 */
190class __EXPORT PersistEngine
191{
192public:
193 /**
194 * These are the modes the Persistence::Engine can work in
195 */
196 enum EngineMode {
197 modeRead,
198 modeWrite
199 };
200
201 /**
202 * Constructs a Persistence::Engine with the specified stream in
203 * the given mode. The stream must be initialized properly prior
204 * to this call or problems will ensue.
205 */
206 PersistEngine(std::iostream& stream, EngineMode mode) throw(PersistException);
207
208 virtual ~PersistEngine();
209
210 // Write operations
211
212 /**
213 * writes a PersistObject from a reference.
214 */
215 inline void write(const PersistObject &object) throw(PersistException)
216 {write(&object); };
217
218 /**
219 * writes a PersistObject from a pointer.
220 */
221 void write(const PersistObject *object) throw(PersistException);
222
223 // writes supported primitive types
224 // shortcut, to make the following more readable
225#define CCXX_ENGINEWRITE_REF(valref) writeBinary((const uint8_t*)&valref,sizeof(valref))
226 inline void write(int8_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
227 inline void write(uint8_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
228 inline void write(int16_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
229 inline void write(uint16_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
230 inline void write(int32_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
231 inline void write(uint32_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
232 inline void write(float i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
233 inline void write(double i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
234 inline void write(bool i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
235#undef CCXX_ENGINEWRITE_REF
236
237 void write(const std::string& str) throw(PersistException);
238
239 // Every write operation boils down to one or more of these
240 void writeBinary(const uint8_t* data, const uint32_t size) throw(PersistException);
241
242 // Read Operations
243
244 /**
245 * reads a PersistObject into a reference overwriting the object.
246 */
247 void read(PersistObject &object) throw(PersistException);
248
249 /**
250 * reads a PersistObject into a pointer allocating memory for the object if necessary.
251 */
252 void read(PersistObject *&object) throw(PersistException);
253
254 // reads supported primitive types
255 // shortcut, to make the following more readable
256#define CCXX_ENGINEREAD_REF(valref) readBinary((uint8_t*)&valref,sizeof(valref))
257 inline void read(int8_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
258 inline void read(uint8_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
259 inline void read(int16_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
260 inline void read(uint16_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
261 inline void read(int32_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
262 inline void read(uint32_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
263 inline void read(float& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
264 inline void read(double& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
265 inline void read(bool &i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
266#undef CCXX_ENGINEREAD_REF
267
268 void read(std::string& str) throw(PersistException);
269
270 // Every read operation boiled down to one or more of these
271 void readBinary(uint8_t* data, uint32_t size) throw(PersistException);
272
273private:
274 /**
275 * reads the actual object data into a pre-instantiated object pointer
276 * by calling the read function of the derived class.
277 */
278 void readObject(PersistObject* object) throw(PersistException);
279
280 /**
281 * reads in a class name, and caches it into the ClassMap.
282 */
283 const std::string readClass() throw(PersistException);
284
285
286 /**
287 * The underlying stream
288 */
289 std::iostream& myUnderlyingStream;
290
291 /**
292 * The mode of the engine. read or write
293 */
294 EngineMode myOperationalMode;
295
296 /**
297 * Typedefs for the Persistence::PersistObject support
298 */
299 typedef std::vector<PersistObject*> ArchiveVector;
300 typedef std::map<PersistObject const*, int32_t> ArchiveMap;
301 typedef std::vector<std::string> ClassVector;
302 typedef std::map<std::string, int32_t> ClassMap;
303
304 ArchiveVector myArchiveVector;
305 ArchiveMap myArchiveMap;
306 ClassVector myClassVector;
307 ClassMap myClassMap;
308};
309
310#define CCXX_RE(ar,ob) ar.read(ob); return ar
311#define CCXX_WE(ar,ob) ar.write(ob); return ar
312
313// Standard >> and << stream operators for PersistObject
314/** @relates PersistEngine */
315inline PersistEngine& operator >>( PersistEngine& ar, PersistObject &ob) throw(PersistException) {CCXX_RE(ar,ob);}
316/** @relates PersistEngine */
317inline PersistEngine& operator >>( PersistEngine& ar, PersistObject *&ob) throw(PersistException) {CCXX_RE(ar,ob);}
318/** @relates PersistEngine */
319inline PersistEngine& operator <<( PersistEngine& ar, PersistObject const &ob) throw(PersistException) {CCXX_WE(ar,ob);}
320/** @relates PersistEngine */
321inline PersistEngine& operator <<( PersistEngine& ar, PersistObject const *ob) throw(PersistException) {CCXX_WE(ar,ob);}
322
323/** @relates PersistEngine */
324inline PersistEngine& operator >>( PersistEngine& ar, int8_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
325/** @relates PersistEngine */
326inline PersistEngine& operator <<( PersistEngine& ar, int8_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
327
328/** @relates PersistEngine */
329inline PersistEngine& operator >>( PersistEngine& ar, uint8_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
330/** @relates PersistEngine */
331inline PersistEngine& operator <<( PersistEngine& ar, uint8_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
332
333/** @relates PersistEngine */
334inline PersistEngine& operator >>( PersistEngine& ar, int16_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
335/** @relates PersistEngine */
336inline PersistEngine& operator <<( PersistEngine& ar, int16_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
337
338/** @relates PersistEngine */
339inline PersistEngine& operator >>( PersistEngine& ar, uint16_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
340/** @relates PersistEngine */
341inline PersistEngine& operator <<( PersistEngine& ar, uint16_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
342
343/** @relates PersistEngine */
344inline PersistEngine& operator >>( PersistEngine& ar, int32_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
345/** @relates PersistEngine */
346inline PersistEngine& operator <<( PersistEngine& ar, int32_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
347
348/** @relates PersistEngine */
349inline PersistEngine& operator >>( PersistEngine& ar, uint32_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
350/** @relates PersistEngine */
351inline PersistEngine& operator <<( PersistEngine& ar, uint32_t ob) throw(PersistException) {CCXX_WE(ar,ob);}
352
353/** @relates PersistEngine */
354inline PersistEngine& operator >>( PersistEngine& ar, float& ob) throw(PersistException) {CCXX_RE(ar,ob);}
355/** @relates PersistEngine */
356inline PersistEngine& operator <<( PersistEngine& ar, float ob) throw(PersistException) {CCXX_WE(ar,ob);}
357
358/** @relates PersistEngine */
359inline PersistEngine& operator >>( PersistEngine& ar, double& ob) throw(PersistException) {CCXX_RE(ar,ob);}
360/** @relates PersistEngine */
361inline PersistEngine& operator <<( PersistEngine& ar, double ob) throw(PersistException) {CCXX_WE(ar,ob);}
362
363/** @relates PersistEngine */
364inline PersistEngine& operator >>( PersistEngine& ar, std::string& ob) throw(PersistException) {CCXX_RE(ar,ob);}
365/** @relates PersistEngine */
366inline PersistEngine& operator <<( PersistEngine& ar, std::string ob) throw(PersistException) {CCXX_WE(ar,ob);}
367
368/** @relates PersistEngine */
369inline PersistEngine& operator >>( PersistEngine& ar, bool& ob) throw(PersistException) {CCXX_RE(ar,ob);}
370/** @relates PersistEngine */
371inline PersistEngine& operator <<( PersistEngine& ar, bool ob) throw(PersistException) {CCXX_WE(ar,ob);}
372
373#undef CCXX_RE
374#undef CCXX_WE
375
376/**
377 * The following are template classes
378 */
379
380/**
381 * @relates PersistEngine
382 * serialize a vector of some serializable content to
383 * the engine
384 */
385template<class T>
386PersistEngine& operator <<( PersistEngine& ar, typename std::vector<T> const& ob) throw(PersistException)
387{
388 ar << (uint32_t)ob.size();
389 for(unsigned int i=0; i < ob.size(); ++i)
390 ar << ob[i];
391 return ar;
392}
393
394/**
395 * @relates PersistEngine
396 * deserialize a vector of deserializable content from
397 * an engine.
398 */
399template<class T>
400PersistEngine& operator >>( PersistEngine& ar, typename std::vector<T>& ob) throw(PersistException)
401{
402 ob.clear();
403 uint32_t siz;
404 ar >> siz;
405 ob.resize(siz);
406 for(uint32_t i=0; i < siz; ++i)
407 ar >> ob[i];
408 return ar;
409}
410
411/**
412 * @relates PersistEngine
413 * serialize a deque of some serializable content to
414 * the engine
415 */
416template<class T>
417PersistEngine& operator <<( PersistEngine& ar, typename std::deque<T> const& ob) throw(PersistException)
418{
419 ar << (uint32_t)ob.size();
420 for(typename std::deque<T>::const_iterator it=ob.begin(); it != ob.end(); ++it)
421 ar << *it;
422 return ar;
423}
424
425/**
426 * @relates PersistEngine
427 * deserialize a deque of deserializable content from
428 * an engine.
429 */
430template<class T>
431PersistEngine& operator >>( PersistEngine& ar, typename std::deque<T>& ob) throw(PersistException)
432{
433 ob.clear();
434 uint32_t siz;
435 ar >> siz;
436 //ob.resize(siz);
437 for(uint32_t i=0; i < siz; ++i) {
438 T node;
439 ar >> node;
440 ob.push_back(node);
441 //ar >> ob[i];
442 }
443 return ar;
444}
445
446/**
447 * @relates PersistEngine
448 * serialize a map with keys/values which both are serializeable
449 * to an engine.
450 */
451template<class Key, class Value>
452PersistEngine& operator <<( PersistEngine& ar, typename std::map<Key,Value> const & ob) throw(PersistException)
453{
454 ar << (uint32_t)ob.size();
455 for(typename std::map<Key,Value>::const_iterator it = ob.begin();it != ob.end();++it)
456 ar << it->first << it->second;
457 return ar;
458}
459
460/**
461 * @relates PersistEngine
462 * deserialize a map with keys/values which both are serializeable
463 * from an engine.
464 */
465template<class Key, class Value>
466PersistEngine& operator >>( PersistEngine& ar, typename std::map<Key,Value>& ob) throw(PersistException)
467{
468 ob.clear();
469 uint32_t siz;
470 ar >> siz;
471 for(uint32_t i=0; i < siz; ++i) {
472 Key a;
473 ar >> a;
474 ar >> ob[a];
475 }
476 return ar;
477}
478
479/**
480 * @relates PersistEngine
481 * serialize a pair of some serializable content to the engine.
482 */
483template<class x, class y>
484PersistEngine& operator <<( PersistEngine& ar, std::pair<x,y> &ob) throw(PersistException)
485{
486 ar << ob.first << ob.second;
487 return ar;
488}
489
490/**
491 * @relates PersistEngine
492 * deserialize a pair of some serializable content to the engine.
493 */
494template<class x, class y>
495PersistEngine& operator >>(PersistEngine& ar, std::pair<x, y> &ob) throw(PersistException)
496{
497 ar >> ob.first >> ob.second;
498 return ar;
499}
500
501END_NAMESPACE
502
503#endif
504#endif
505#endif