blob: b55c1917df070c9536d7592e9414a2a326fb6848 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39/**
40 * @file persist.h
41 * @short Persistence library classes.
42 **/
43
44#ifndef CCXX_PERSIST_H_
45#define CCXX_PERSIST_H_
46
47#ifndef CCXX_CONFIG_H_
48#include <cc++/config.h>
49#endif
50
51#ifndef CCXX_EXCEPTIONS_H_
52#include <cc++/exception.h>
53#endif
54
55#ifndef CCXX_MISSING_H_
56#include <cc++/missing.h>
57#endif
58
59#ifndef CCXX_STRING_H_
60#include <cc++/string.h>
61#endif
62
63#ifdef HAVE_ZLIB_H
64#ifndef NO_COMPRESSION
65#include <zlib.h>
66#endif
67#else
68#define NO_COMPRESSION
69#endif
70
71#include <iostream>
72#include <string>
73#include <vector>
74#include <deque>
75#include <map>
76
77#ifdef CCXX_NAMESPACES
78namespace ost {
79#define NS_PREFIX ost::
80#else
81#define NS_PREFIX
82#endif
83
84#ifdef CCXX_EXCEPTIONS
85#ifdef COMMON_STD_EXCEPTION
86
87class __EXPORT PersistException : public Exception
88{
89public:
90 PersistException(const String &what) : Exception(what) {};
91};
92
93#else
94
95class __EXPORT PersistException
96{
97public:
98 PersistException(const String& reason);
99 inline const String& getString() const
100 {return Exception::getString();};
101
102 virtual ~PersistException() {} throw();
103protected:
104 String _what;
105};
106
107#endif
108#endif
109
110// This typedef allows us to declare NewBaseObjectFunction now
111typedef class BaseObject* (*NewBaseObjectFunction) (void);
112
113/**
114 * This class manages the types for generation of the persistent objects.
115 * Its data structures are managed automatically by the system. They are
116 * implicitly filled by the constructors who declare classes to the system.
117 *
118 * @author Daniel Silverstone
119 * @short Type manager for persistence engine.
120 */
121class __EXPORT TypeManager
122{
123public:
124
125 /**
126 * This manages a registration to the typemanager - attempting to
127 * remove problems with the optimisers
128 */
129 class Registration
130 {
131 public:
132 Registration(const char* name, NewBaseObjectFunction func);
133 virtual ~Registration();
134 private:
135 String myName;
136 };
137
138 /**
139 * This adds a new construction function to the type manager
140 */
141 static void add(const char* name, NewBaseObjectFunction construction);
142
143 /**
144 * And this one removes a type from the managers lists
145 */
146 static void remove(const char* name);
147
148 /**
149 * This function creates a new object of the required type and
150 * returns a pointer to it. NULL is returned if we couldn't find
151 * the type
152 */
153 static BaseObject* createInstanceOf(const char* name);
154
155 typedef std::map<String,NewBaseObjectFunction> StringFunctionMap;
156};
157
158
159/*
160 * The following defines are used to declare and define the relevant code
161 * to allow a class to use the Persistence::Engine code.
162 */
163
164#define DECLARE_PERSISTENCE(ClassType) \
165 public: \
166 friend NS_PREFIX Engine& operator>>( NS_PREFIX Engine& ar, ClassType *&ob); \
167 friend NS_PREFIX Engine& operator<<( NS_PREFIX Engine& ar, ClassType const &ob); \
168 friend NS_PREFIX BaseObject *createNew##ClassType(); \
169 virtual const char* getPersistenceID() const; \
170 static NS_PREFIX TypeManager::Registration registrationFor##ClassType;
171
172#define IMPLEMENT_PERSISTENCE(ClassType, FullyQualifiedName) \
173 NS_PREFIX BaseObject *createNew##ClassType() { return new ClassType; } \
174 const char* ClassType::getPersistenceID() const {return FullyQualifiedName;} \
175 NS_PREFIX Engine& operator>>(NS_PREFIX Engine& ar, ClassType &ob) \
176 { ar >> (NS_PREFIX BaseObject &) ob; return ar; } \
177 NS_PREFIX Engine& operator>>(NS_PREFIX Engine& ar, ClassType *&ob) \
178 { ar >> (NS_PREFIX BaseObject *&) ob; return ar; } \
179 NS_PREFIX Engine& operator<<(NS_PREFIX Engine& ar, ClassType const &ob) \
180 { ar << (NS_PREFIX BaseObject const *)&ob; return ar; } \
181 NS_PREFIX TypeManager::Registration \
182 ClassType::registrationFor##ClassType(FullyQualifiedName, \
183 createNew##ClassType);
184
185class Engine;
186
187/**
188 * BaseObject
189 *
190 * This object is the base for all Persistent data which is not
191 * natively serialised by the Persistence::Engine
192 *
193 * It registers itself with the Persistence::TypeManager
194 * using a global constructor function. A matching deregister call
195 * is made in a global destructor, to allow DLL's to use the
196 * Persistence::Engine in a main executable.
197 *
198 * Persistable objects must never maintain bad pointers. If a pointer
199 * doesn't point to something valid, it must be NULL. This is so
200 * the persistence engine knows whether to allocate memory for an object
201 * or whether the memory has been pre-allocated.
202 *
203 * @author Daniel Silverstone
204 * @short Base class for classes that will be persistent.
205 */
206class __EXPORT BaseObject
207{
208public:
209 /**
210 * This constructor is used in serialisation processes.
211 * It is called in CreateNewInstance in order to create
212 * an instance of the class to have Read() called on it.
213 */
214 BaseObject();
215
216 /**
217 * Default destructor
218 */
219 virtual ~BaseObject();
220
221 /**
222 * This returns the ID of the persistent object (Its type)
223 */
224 virtual const char* getPersistenceID() const;
225
226 /**
227 * This method is used to write to the Persistence::Engine
228 * It is not equivalent to the << operator as it writes only the data
229 * and not the object type etc.
230 */
231 virtual bool write(Engine& archive) const;
232
233 /**
234 * This method is used to read from a Persistence::Engine
235 * It is not equivalent to the >> operator as it does no
236 * typesafety or anything.
237 */
238 virtual bool read(Engine& archive);
239};
240
241
242/**
243 * Engine
244 *
245 * This class constructs on a standard C++ STL stream and then
246 * operates in the mode specified. The stream passed into the
247 * constructor must be a binary mode to function properly.
248 *
249 * @author Daniel Silverstone
250 * @short stream serialization of persistent classes.
251 */
252class __EXPORT Engine
253{
254public:
255 /**
256 * These are the modes the Persistence::Engine can work in
257 */
258 enum EngineMode {
259 modeRead,
260 modeWrite
261 };
262
263 /**
264 * Constructs a Persistence::Engine with the specified stream in
265 * the given mode. The stream must be initialised properly prior
266 * to this call or problems will ensue. If built using zlib compress
267 * can be used to enable compression
268 */
269 Engine(std::iostream& stream, EngineMode mode, bool compress=true) THROWS (PersistException);
270
271 /**
272 * This Flushes the buffers and closes the Persistence::Engine
273 * this must happen before the underlying stream is shut down
274 */
275 void sync();
276
277 /**
278 * This says there are more objects to deserialize
279 */
280 bool more();
281
282 virtual ~Engine();
283
284
285 // Write operations
286
287 /**
288 * writes a BaseObject from a reference.
289 */
290 void write(const BaseObject &object) THROWS (PersistException)
291 { write(&object); };
292
293 /**
294 * writes a BaseObject from a pointer.
295 */
296 void write(const BaseObject *object) THROWS (PersistException);
297
298 // writes supported primitive types
299 // shortcut, to make the following more readable
300#define CCXX_ENGINEWRITE_REF(valref) writeBinary((const uint8*)&valref,sizeof(valref))
301 void write(int8 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
302 void write(uint8 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
303 void write(int16 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
304 void write(uint16 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
305 void write(int32 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
306 void write(uint32 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
307#ifdef HAVE_64_BITS
308 void write(int64 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
309 void write(uint64 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
310#endif
311 void write(float i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
312 void write(double i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); }
313#undef CCXX_ENGINEWRITE_REF
314
315 void write(const String& str) THROWS (PersistException);
316 void write(const std::string& str) THROWS (PersistException);
317
318 // Every write operation boils down to one or more of these
319 void writeBinary(const uint8* data, const uint32 size) THROWS (PersistException);
320
321
322 // Read Operations
323
324 /**
325 * reads a BaseObject into a reference overwriting the object.
326 */
327 void read(BaseObject &object) THROWS (PersistException);
328
329 /**
330 * reads a BaseObject into a pointer allocating memory for the object if necessary.
331 */
332 void read(BaseObject *&object) THROWS (PersistException);
333
334 // reads supported primitive types
335 // shortcut, to make the following more readable
336#define CCXX_ENGINEREAD_REF(valref) readBinary((uint8*)&valref,sizeof(valref))
337 void read(int8& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
338 void read(uint8& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
339 void read(int16& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
340 void read(uint16& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
341 void read(int32& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
342 void read(uint32& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
343#ifdef HAVE_64_BITS
344 void read(int64& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
345 void read(uint64& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
346#endif
347 void read(float& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
348 void read(double& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); }
349#undef CCXX_ENGINEREAD_REF
350
351 void read(String& str) THROWS (PersistException);
352 void read(std::string& str) THROWS (PersistException);
353
354 // Every read operation boild down to one or more of these
355 void readBinary(uint8* data, uint32 size) THROWS (PersistException);
356
357private:
358 /**
359 * reads the actual object data into a pre-instantiated object pointer
360 * by calling the read function of the derived class.
361 */
362 void readObject(BaseObject* object) THROWS (PersistException);
363
364 /**
365 * reads in a class name, and caches it into the ClassMap.
366 */
367 const String readClass() THROWS (PersistException);
368
369
370 /**
371 * The underlying stream
372 */
373 std::iostream& myUnderlyingStream;
374
375 /**
376 * The mode of the engine. read or write
377 */
378 EngineMode myOperationalMode;
379
380 /**
381 * Typedefs for the Persistence::BaseObject support
382 */
383 typedef std::vector<BaseObject*> ArchiveVector;
384 typedef std::map<BaseObject const*, int32> ArchiveMap;
385 typedef std::vector<String> ClassVector;
386 typedef std::map<String, int32> ClassMap;
387
388 ArchiveVector myArchiveVector;
389 ArchiveMap myArchiveMap;
390 ClassVector myClassVector;
391 ClassMap myClassMap;
392
393 // Compression support
394 bool use_compression; // valid onlry if NO_COMPRESSION is false
395#ifndef NO_COMPRESSION
396 z_stream myZStream;
397 uint8* myCompressedDataBuffer;
398 uint8* myUncompressedDataBuffer;
399 uint8* myLastUncompressedDataRead;
400#endif
401};
402
403// Standard >> and << stream operators for BaseObject
404/** @relates Engine */
405__EXPORT Engine& operator >>( Engine& ar, BaseObject &ob) THROWS (PersistException);
406/** @relates Engine */
407__EXPORT Engine& operator >>( Engine& ar, BaseObject *&ob) THROWS (PersistException);
408/** @relates Engine */
409__EXPORT Engine& operator <<( Engine& ar, BaseObject const &ob) THROWS (PersistException);
410/** @relates Engine */
411__EXPORT Engine& operator <<( Engine& ar, BaseObject const *ob) THROWS (PersistException);
412
413/** @relates Engine */
414__EXPORT Engine& operator >>( Engine& ar, int8& ob) THROWS (PersistException);
415/** @relates Engine */
416__EXPORT Engine& operator <<( Engine& ar, int8 ob) THROWS (PersistException);
417
418/** @relates Engine */
419__EXPORT Engine& operator >>( Engine& ar, uint8& ob) THROWS (PersistException);
420/** @relates Engine */
421__EXPORT Engine& operator <<( Engine& ar, uint8 ob) THROWS (PersistException);
422
423/** @relates Engine */
424__EXPORT Engine& operator >>( Engine& ar, int16& ob) THROWS (PersistException);
425/** @relates Engine */
426__EXPORT Engine& operator <<( Engine& ar, int16 ob) THROWS (PersistException);
427
428/** @relates Engine */
429__EXPORT Engine& operator >>( Engine& ar, uint16& ob) THROWS (PersistException);
430/** @relates Engine */
431__EXPORT Engine& operator <<( Engine& ar, uint16 ob) THROWS (PersistException);
432
433/** @relates Engine */
434__EXPORT Engine& operator >>( Engine& ar, int32& ob) THROWS (PersistException);
435/** @relates Engine */
436__EXPORT Engine& operator <<( Engine& ar, int32 ob) THROWS (PersistException);
437
438/** @relates Engine */
439__EXPORT Engine& operator >>( Engine& ar, uint32& ob) THROWS (PersistException);
440/** @relates Engine */
441__EXPORT Engine& operator <<( Engine& ar, uint32 ob) THROWS (PersistException);
442
443#ifdef HAVE_64_BITS
444/** @relates Engine */
445__EXPORT Engine& operator >>( Engine& ar, int64& ob) THROWS (PersistException);
446/** @relates Engine */
447__EXPORT Engine& operator <<( Engine& ar, int64 ob) THROWS (PersistException);
448
449/** @relates Engine */
450__EXPORT Engine& operator >>( Engine& ar, uint64& ob) THROWS (PersistException);
451/** @relates Engine */
452__EXPORT Engine& operator <<( Engine& ar, uint64 ob) THROWS (PersistException);
453#endif
454
455/** @relates Engine */
456__EXPORT Engine& operator >>( Engine& ar, float& ob) THROWS (PersistException);
457/** @relates Engine */
458__EXPORT Engine& operator <<( Engine& ar, float ob) THROWS (PersistException);
459
460/** @relates Engine */
461__EXPORT Engine& operator >>( Engine& ar, double& ob) THROWS (PersistException);
462/** @relates Engine */
463__EXPORT Engine& operator <<( Engine& ar, double ob) THROWS (PersistException);
464
465/** @relates Engine */
466__EXPORT Engine& operator >>( Engine& ar, String& ob) THROWS (PersistException);
467/** @relates Engine */
468__EXPORT Engine& operator <<( Engine& ar, String ob) THROWS (PersistException);
469
470/** @relates Engine */
471__EXPORT Engine& operator >>( Engine& ar, std::string& ob) THROWS (PersistException);
472/** @relates Engine */
473__EXPORT Engine& operator <<( Engine& ar, std::string ob) THROWS (PersistException);
474
475/** @relates Engine */
476__EXPORT Engine& operator >>( Engine& ar, bool& ob) THROWS (PersistException);
477/** @relates Engine */
478__EXPORT Engine& operator <<( Engine& ar, bool ob) THROWS (PersistException);
479
480/**
481 * The following are templated classes
482 */
483
484/**
485 * @relates Engine
486 * serialize a vector of some serializable content to
487 * the engine
488 */
489template<class T>
490Engine& operator <<( Engine& ar, typename std::vector<T> const& ob) THROWS (PersistException)
491{
492 ar << (uint32)ob.size();
493 for(unsigned int i=0; i < ob.size(); ++i)
494 ar << ob[i];
495 return ar;
496}
497
498/**
499 * @relates Engine
500 * deserialize a vector of deserializable content from
501 * an engine.
502 */
503template<class T>
504Engine& operator >>( Engine& ar, typename std::vector<T>& ob) THROWS (PersistException)
505{
506 ob.clear();
507 uint32 siz;
508 ar >> siz;
509 ob.resize(siz);
510 for(uint32 i=0; i < siz; ++i)
511 ar >> ob[i];
512 return ar;
513}
514
515/**
516 * @relates Engine
517 * serialize a deque of some serializable content to
518 * the engine
519 */
520template<class T>
521Engine& operator <<( Engine& ar, typename std::deque<T> const& ob) THROWS (PersistException)
522{
523 ar << (uint32)ob.size();
524 for(typename std::deque<T>::const_iterator it=ob.begin(); it != ob.end(); ++it)
525 ar << *it;
526 return ar;
527}
528
529/**
530 * @relates Engine
531 * deserialize a deque of deserializable content from
532 * an engine.
533 */
534template<class T>
535Engine& operator >>( Engine& ar, typename std::deque<T>& ob) THROWS (PersistException)
536{
537 ob.clear();
538 uint32 siz;
539 ar >> siz;
540 //ob.resize(siz);
541 for(uint32 i=0; i < siz; ++i) {
542 T node;
543 ar >> node;
544 ob.push_back(node);
545 //ar >> ob[i];
546 }
547 return ar;
548}
549
550/**
551 * @relates Engine
552 * serialize a map with keys/values which both are serializeable
553 * to an engine.
554 */
555template<class Key, class Value>
556Engine& operator <<( Engine& ar, typename std::map<Key,Value> const & ob) THROWS (PersistException)
557{
558 ar << (uint32)ob.size();
559 for(typename std::map<Key,Value>::const_iterator it = ob.begin();it != ob.end();++it)
560 ar << it->first << it->second;
561 return ar;
562}
563
564/**
565 * @relates Engine
566 * deserialize a map with keys/values which both are serializeable
567 * from an engine.
568 */
569template<class Key, class Value>
570Engine& operator >>( Engine& ar, typename std::map<Key,Value>& ob) THROWS (PersistException)
571{
572 ob.clear();
573 uint32 siz;
574 ar >> siz;
575 for(uint32 i=0; i < siz; ++i) {
576 Key a;
577 ar >> a;
578 ar >> ob[a];
579 }
580 return ar;
581}
582
583/**
584 * @relates Engine
585 * serialize a pair of some serializable content to the engine.
586 */
587template<class x, class y>
588Engine& operator <<( Engine& ar, std::pair<x,y> &ob) THROWS (PersistException)
589{
590 ar << ob.first << ob.second;
591 return ar;
592}
593
594/**
595 * @relates Engine
596 * deserialize a pair of some serializable content to the engine.
597 */
598template<class x, class y>
599Engine& operator >>(Engine& ar, std::pair<x, y> &ob) THROWS (PersistException)
600{
601 ar >> ob.first >> ob.second;
602 return ar;
603}
604
605#ifdef CCXX_NAMESPACES
606}
607#endif
608
609#endif
610
611/** EMACS **
612 * Local variables:
613 * mode: c++
614 * c-basic-offset: 4
615 * End:
616 */