// Copyright (C) 1999-2005 Open Source Telecom Corporation. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. // // This exception applies only to the code released under the name GNU // Common C++. If you copy code from other releases into a copy of GNU // Common C++, as the General Public License permits, the exception does // not apply to the code that you add in this way. To avoid misleading // anyone as to the status of such modified files, you must delete // this exception notice from them. // // If you write modifications of your own for GNU Common C++, it is your choice // whether to permit this exception to apply to your modifications. // If you do not wish that, delete this exception notice. // /** * @file persist.h * @short Persistence library classes. **/ #ifndef CCXX_PERSIST_H_ #define CCXX_PERSIST_H_ #ifndef CCXX_CONFIG_H_ #include #endif #ifndef CCXX_EXCEPTIONS_H_ #include #endif #ifndef CCXX_MISSING_H_ #include #endif #ifndef CCXX_STRING_H_ #include #endif #ifdef HAVE_ZLIB_H #ifndef NO_COMPRESSION #include #endif #else #define NO_COMPRESSION #endif #include #include #include #include #include #ifdef CCXX_NAMESPACES namespace ost { #define NS_PREFIX ost:: #else #define NS_PREFIX #endif #ifdef CCXX_EXCEPTIONS #ifdef COMMON_STD_EXCEPTION class __EXPORT PersistException : public Exception { public: PersistException(const String &what) : Exception(what) {}; }; #else class __EXPORT PersistException { public: PersistException(const String& reason); inline const String& getString() const {return Exception::getString();}; virtual ~PersistException() {} throw(); protected: String _what; }; #endif #endif // This typedef allows us to declare NewBaseObjectFunction now typedef class BaseObject* (*NewBaseObjectFunction) (void); /** * This class manages the types for generation of the persistent objects. * Its data structures are managed automatically by the system. They are * implicitly filled by the constructors who declare classes to the system. * * @author Daniel Silverstone * @short Type manager for persistence engine. */ class __EXPORT TypeManager { public: /** * This manages a registration to the typemanager - attempting to * remove problems with the optimisers */ class Registration { public: Registration(const char* name, NewBaseObjectFunction func); virtual ~Registration(); private: String myName; }; /** * This adds a new construction function to the type manager */ static void add(const char* name, NewBaseObjectFunction construction); /** * And this one removes a type from the managers lists */ static void remove(const char* name); /** * This function creates a new object of the required type and * returns a pointer to it. NULL is returned if we couldn't find * the type */ static BaseObject* createInstanceOf(const char* name); typedef std::map StringFunctionMap; }; /* * The following defines are used to declare and define the relevant code * to allow a class to use the Persistence::Engine code. */ #define DECLARE_PERSISTENCE(ClassType) \ public: \ friend NS_PREFIX Engine& operator>>( NS_PREFIX Engine& ar, ClassType *&ob); \ friend NS_PREFIX Engine& operator<<( NS_PREFIX Engine& ar, ClassType const &ob); \ friend NS_PREFIX BaseObject *createNew##ClassType(); \ virtual const char* getPersistenceID() const; \ static NS_PREFIX TypeManager::Registration registrationFor##ClassType; #define IMPLEMENT_PERSISTENCE(ClassType, FullyQualifiedName) \ NS_PREFIX BaseObject *createNew##ClassType() { return new ClassType; } \ const char* ClassType::getPersistenceID() const {return FullyQualifiedName;} \ NS_PREFIX Engine& operator>>(NS_PREFIX Engine& ar, ClassType &ob) \ { ar >> (NS_PREFIX BaseObject &) ob; return ar; } \ NS_PREFIX Engine& operator>>(NS_PREFIX Engine& ar, ClassType *&ob) \ { ar >> (NS_PREFIX BaseObject *&) ob; return ar; } \ NS_PREFIX Engine& operator<<(NS_PREFIX Engine& ar, ClassType const &ob) \ { ar << (NS_PREFIX BaseObject const *)&ob; return ar; } \ NS_PREFIX TypeManager::Registration \ ClassType::registrationFor##ClassType(FullyQualifiedName, \ createNew##ClassType); class Engine; /** * BaseObject * * This object is the base for all Persistent data which is not * natively serialised by the Persistence::Engine * * It registers itself with the Persistence::TypeManager * using a global constructor function. A matching deregister call * is made in a global destructor, to allow DLL's to use the * Persistence::Engine in a main executable. * * Persistable objects must never maintain bad pointers. If a pointer * doesn't point to something valid, it must be NULL. This is so * the persistence engine knows whether to allocate memory for an object * or whether the memory has been pre-allocated. * * @author Daniel Silverstone * @short Base class for classes that will be persistent. */ class __EXPORT BaseObject { public: /** * This constructor is used in serialisation processes. * It is called in CreateNewInstance in order to create * an instance of the class to have Read() called on it. */ BaseObject(); /** * Default destructor */ virtual ~BaseObject(); /** * This returns the ID of the persistent object (Its type) */ virtual const char* getPersistenceID() const; /** * This method is used to write to the Persistence::Engine * It is not equivalent to the << operator as it writes only the data * and not the object type etc. */ virtual bool write(Engine& archive) const; /** * This method is used to read from a Persistence::Engine * It is not equivalent to the >> operator as it does no * typesafety or anything. */ virtual bool read(Engine& archive); }; /** * Engine * * This class constructs on a standard C++ STL stream and then * operates in the mode specified. The stream passed into the * constructor must be a binary mode to function properly. * * @author Daniel Silverstone * @short stream serialization of persistent classes. */ class __EXPORT Engine { public: /** * These are the modes the Persistence::Engine can work in */ enum EngineMode { modeRead, modeWrite }; /** * Constructs a Persistence::Engine with the specified stream in * the given mode. The stream must be initialised properly prior * to this call or problems will ensue. */ Engine(std::iostream& stream, EngineMode mode) THROWS (PersistException); /** * This Flushes the buffers and closes the Persistence::Engine * this must happen before the underlying stream is shut down */ void sync(); virtual ~Engine(); // Write operations /** * writes a BaseObject from a reference. */ void write(const BaseObject &object) THROWS (PersistException) { write(&object); }; /** * writes a BaseObject from a pointer. */ void write(const BaseObject *object) THROWS (PersistException); // writes supported primitive types // shortcut, to make the following more readable #define CCXX_ENGINEWRITE_REF(valref) writeBinary((const uint8*)&valref,sizeof(valref)) void write(int8 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(uint8 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(int16 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(uint16 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(int32 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(uint32 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } #ifdef HAVE_64_BITS void write(int64 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(uint64 i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } #endif void write(float i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } void write(double i) THROWS (PersistException) { CCXX_ENGINEWRITE_REF(i); } #undef CCXX_ENGINEWRITE_REF void write(const String& str) THROWS (PersistException); void write(const std::string& str) THROWS (PersistException); // Every write operation boils down to one or more of these void writeBinary(const uint8* data, const uint32 size) THROWS (PersistException); // Read Operations /** * reads a BaseObject into a reference overwriting the object. */ void read(BaseObject &object) THROWS (PersistException); /** * reads a BaseObject into a pointer allocating memory for the object if necessary. */ void read(BaseObject *&object) THROWS (PersistException); // reads supported primitive types // shortcut, to make the following more readable #define CCXX_ENGINEREAD_REF(valref) readBinary((uint8*)&valref,sizeof(valref)) void read(int8& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(uint8& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(int16& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(uint16& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(int32& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(uint32& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } #ifdef HAVE_64_BITS void read(int64& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(uint64& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } #endif void read(float& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } void read(double& i) THROWS (PersistException) { CCXX_ENGINEREAD_REF(i); } #undef CCXX_ENGINEREAD_REF void read(String& str) THROWS (PersistException); void read(std::string& str) THROWS (PersistException); // Every read operation boild down to one or more of these void readBinary(uint8* data, uint32 size) THROWS (PersistException); private: /** * reads the actual object data into a pre-instantiated object pointer * by calling the read function of the derived class. */ void readObject(BaseObject* object) THROWS (PersistException); /** * reads in a class name, and caches it into the ClassMap. */ const String readClass() THROWS (PersistException); /** * The underlying stream */ std::iostream& myUnderlyingStream; /** * The mode of the engine. read or write */ EngineMode myOperationalMode; /** * Typedefs for the Persistence::BaseObject support */ typedef std::vector ArchiveVector; typedef std::map ArchiveMap; typedef std::vector ClassVector; typedef std::map ClassMap; ArchiveVector myArchiveVector; ArchiveMap myArchiveMap; ClassVector myClassVector; ClassMap myClassMap; // Compression support #ifndef NO_COMPRESSION z_stream myZStream; uint8* myCompressedDataBuffer; uint8* myUncompressedDataBuffer; uint8* myLastUncompressedDataRead; #endif }; // Standard >> and << stream operators for BaseObject /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, BaseObject &ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, BaseObject *&ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, BaseObject const &ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, BaseObject const *ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, int8& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, int8 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, uint8& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, uint8 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, int16& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, int16 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, uint16& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, uint16 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, int32& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, int32 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, uint32& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, uint32 ob) THROWS (PersistException); #ifdef HAVE_64_BITS /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, int64& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, int64 ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, uint64& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, uint64 ob) THROWS (PersistException); #endif /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, float& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, float ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, double& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, double ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, String& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, String ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, std::string& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, std::string ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator >>( Engine& ar, bool& ob) THROWS (PersistException); /** @relates Engine */ __EXPORT Engine& operator <<( Engine& ar, bool ob) THROWS (PersistException); /** * The following are templated classes */ /** * @relates Engine * serialize a vector of some serializable content to * the engine */ template Engine& operator <<( Engine& ar, typename std::vector const& ob) THROWS (PersistException) { ar << (uint32)ob.size(); for(unsigned int i=0; i < ob.size(); ++i) ar << ob[i]; return ar; } /** * @relates Engine * deserialize a vector of deserializable content from * an engine. */ template Engine& operator >>( Engine& ar, typename std::vector& ob) THROWS (PersistException) { ob.clear(); uint32 siz; ar >> siz; ob.resize(siz); for(uint32 i=0; i < siz; ++i) ar >> ob[i]; return ar; } /** * @relates Engine * serialize a deque of some serializable content to * the engine */ template Engine& operator <<( Engine& ar, typename std::deque const& ob) THROWS (PersistException) { ar << (uint32)ob.size(); for(typename std::deque::const_iterator it=ob.begin(); it != ob.end(); ++it) ar << *it; return ar; } /** * @relates Engine * deserialize a deque of deserializable content from * an engine. */ template Engine& operator >>( Engine& ar, typename std::deque& ob) THROWS (PersistException) { ob.clear(); uint32 siz; ar >> siz; //ob.resize(siz); for(uint32 i=0; i < siz; ++i) { T node; ar >> node; ob.push_back(node); //ar >> ob[i]; } return ar; } /** * @relates Engine * serialize a map with keys/values which both are serializeable * to an engine. */ template Engine& operator <<( Engine& ar, typename std::map const & ob) THROWS (PersistException) { ar << (uint32)ob.size(); for(typename std::map::const_iterator it = ob.begin();it != ob.end();++it) ar << it->first << it->second; return ar; } /** * @relates Engine * deserialize a map with keys/values which both are serializeable * from an engine. */ template Engine& operator >>( Engine& ar, typename std::map& ob) THROWS (PersistException) { ob.clear(); uint32 siz; ar >> siz; for(uint32 i=0; i < siz; ++i) { Key a; ar >> a; ar >> ob[a]; } return ar; } /** * @relates Engine * serialize a pair of some serializable content to the engine. */ template Engine& operator <<( Engine& ar, std::pair &ob) THROWS (PersistException) { ar << ob.first << ob.second; return ar; } /** * @relates Engine * deserialize a pair of some serializable content to the engine. */ template Engine& operator >>(Engine& ar, std::pair &ob) THROWS (PersistException) { ar >> ob.first >> ob.second; return ar; } #ifdef CCXX_NAMESPACES } #endif #endif /** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */