Source: ../common/persist.h
|
|
|
|
// Copyright (C) 1999-2000 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 to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// 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 Common C++. If you copy code from other releases into a copy of
// 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 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.
#ifndef __CCXX_PERSIST_H__
#define __CCXX_PERSIST_H__
#ifndef __CCXX_CONFIG_H__
#include <cc++/config.h>
#endif
#ifndef __CCXX_MACROS_H__
#include <cc++/macros.h>
#else
#ifdef __CCXX_NAMESPACE_H__
#include <cc++/macros.h>
#endif
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#else
#define NO_COMPRESSION
#endif
#include <iostream.h>
#include <string>
#include <vector>
#include <map>
#ifdef __WIN32__
class __EXPORT PersistException;
class __EXPORT Engine;
class __EXPORT TypeManager;
class __EXPORT BaseObject;
#endif
class PersistException
{
public:
PersistException(string const& reason);
string const& GetMessage() const;
virtual ~PersistException();
protected:
string myMessage;
};
class Engine;
// 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 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)
: myName(name) { TypeManager::Add(name,func); }
~Registration() { TypeManager::Remove(myName.c_str()); }
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 map<string,NewBaseObjectFunction> 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 Engine& operator>>(Engine& ar, ClassType *&ob);\
friend Engine& operator<<(Engine& ar, ClassType const *&ob);\
friend BaseObject *CreateNew##ClassType();\
virtual const char* GetPersistenceID() const;\
static TypeManager::Registration RegistrationFor##ClassType;
#define IMPLEMENT_PERSISTENCE(ClassType,FullyQualifiedName)\
BaseObject *CreateNew##ClassType() { return new ClassType; }\
const char* ClassType::GetPersistenceID() const { return FullyQualifiedName; }\
Engine& operator>>(Engine& ar, ClassType *&ob)\
{ ar >> (BaseObject *&) ob; return ar; }\
Engine& operator<<(Engine& ar, ClassType const *ob)\
{ ar << (BaseObject const *)ob; return ar; }\
TypeManager::Registration ClassType::RegistrationFor##ClassType(FullyQualifiedName,CreateNew##ClassType);
/**
* 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.
*
* @author Daniel Silverstone
* @short Base class for classes that will be persistent.
*/
class BaseObject
{
public:
/**
* This returns the ID of the persistent object (Its type)
*/
virtual const char* GetPersistenceID() const;
/**
* 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 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.
*
* @author Daniel Silverstone
* @short stream serialization of persistent classes.
*/
class Engine
{
public:
/**
* If problems happen which are fatal - expect one of these thrown at you
*/
class Exception
{
public:
Exception(const char* msg) : message(msg) {;}
const char* GetMessage() { return message.c_str(); }
private:
string message;
};
/**
* 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(iostream& stream, EngineMode mode);
/**
* This Flushes the buffers and closes the Persistence::Engine
* this must happen before the underlying stream is shut down
*/
~Engine();
// Write operations
void Write(const BaseObject *object);
void Write(int8 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(uint8 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(int16 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(uint16 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(int32 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(uint32 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(int64 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(uint64 i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(float i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(double i) { WriteBinary((const uint8*)&i,sizeof(i)); }
void Write(const string& str);
// Every write operation boils down to one or more of theses
void WriteBinary(const uint8* data, const uint32 size);
// Read Operations
void Read(BaseObject *&object);
void Read(int8& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(uint8& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(int16& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(uint16& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(int32& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(uint32& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(int64& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(uint64& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(float& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(double& i) { ReadBinary((uint8*)&i,sizeof(i)); }
void Read(string& str);
// Every read operation boild down to one or more of these
void ReadBinary(uint8* data, uint32 size);
private:
/**
* The underlying stream
*/
iostream& myUnderlyingStream;
/**
* The mode of the engine
*/
EngineMode myOperationalMode;
/**
* Typedefs for the Persistence::BaseObject support
*/
typedef vector<BaseObject*> ArchiveVector;
typedef map<BaseObject const*, int32> ArchiveMap;
typedef vector<string> ClassVector;
typedef map<string, int32> 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
Engine& operator >>( Engine& ar, BaseObject *&ob);
Engine& operator <<( Engine& ar, BaseObject const *ob);
Engine& operator >>( Engine& ar, int8& ob);
Engine& operator <<( Engine& ar, int8 ob);
Engine& operator >>( Engine& ar, uint8& ob);
Engine& operator <<( Engine& ar, uint8 ob);
Engine& operator >>( Engine& ar, int16& ob);
Engine& operator <<( Engine& ar, int16 ob);
Engine& operator >>( Engine& ar, uint16& ob);
Engine& operator <<( Engine& ar, uint16 ob);
Engine& operator >>( Engine& ar, int32& ob);
Engine& operator <<( Engine& ar, int32 ob);
Engine& operator >>( Engine& ar, uint32& ob);
Engine& operator <<( Engine& ar, uint32 ob);
Engine& operator >>( Engine& ar, int64& ob);
Engine& operator <<( Engine& ar, int64 ob);
Engine& operator >>( Engine& ar, uint64& ob);
Engine& operator <<( Engine& ar, uint64 ob);
Engine& operator >>( Engine& ar, float& ob);
Engine& operator <<( Engine& ar, float ob);
Engine& operator >>( Engine& ar, double& ob);
Engine& operator <<( Engine& ar, double ob);
Engine& operator >>( Engine& ar, string& ob);
Engine& operator <<( Engine& ar, string ob);
Engine& operator >>( Engine& ar, bool& ob);
Engine& operator <<( Engine& ar, bool ob);
/**
* The following are templated classes
*/
template<class T>
Engine& operator <<( Engine& ar, vector<T> const& ob)
{
ar << ob.size();
for(int i=0; i < ob.size(); ++i)
ar << ob[i];
return ar;
}
template<class T>
Engine& operator >>( Engine& ar, vector<T>& ob)
{
ob.clear();
uint32 siz;
ar >> siz;
ob.resize(siz);
for(int i=0; i < siz; ++i)
{
ar >> ob[i];
}
return ar;
}
template<class Key, class Value>
Engine& operator <<( Engine& ar, map<Key,Value> const & ob)
{
ar << ob.size();
for(map<Key,Value>::const_iterator it = ob.begin(); it != ob.end(); ++it)
{
ar << it->first << it->second;
}
return ar;
}
template<class Key, class Value>
Engine& operator >>( Engine& ar, map<Key,Value>& ob)
{
ob.clear();
uint32 siz;
ar >> siz;
for(int i=0; i < siz; ++i)
{
Key a;
ar >> a;
ar >> ob[a];
}
return ar;
}
#ifdef __CCXX_NAMESPACE_H__
#undef __CCXX_NAMESPACE_H__
#include <cc++/namespace.h>
#endif
#endif
Generated by: dyfet@home.sys on Fri May 12 08:41:04 200. |