Source: ../common/persist.h


Annotated List
Files
Globals
Hierarchy
Index
// 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

#ifdef	HAVE_ZLIB_H
#include <zlib.h>
#else
#define	NO_COMPRESSION
#endif

#include <iostream>
#include <string>
#include <vector>
#include <map>

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);

  private:
	typedef map<string,NewBaseObjectFunction> StringFunctionMap;
	static StringFunctionMap ourInstantiationFunctions;
  };


  /*
   * 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];
  }
  
  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];
	  }
  }

  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;
	  }
  }

  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];
	  }
  }

#endif


Generated by: dyfet@home.sys on Wed Mar 15 14:08:35 200.