2009-04-16 14:14:13 +03:00
# ifndef __CONNECTION_H__
# define __CONNECTION_H__
# include "../global.h"
# include <string>
# include <vector>
# include <set>
# include <list>
# include <typeinfo> //XXX this is in namespace std if you want w/o use typeinfo.h?
2010-06-29 04:48:12 +03:00
# include <assert.h>
2009-04-16 14:14:13 +03:00
# include <boost/type_traits/is_fundamental.hpp>
# include <boost/type_traits/is_enum.hpp>
# include <boost/type_traits/is_pointer.hpp>
# include <boost/type_traits/is_class.hpp>
2009-10-06 17:02:47 +03:00
# include <boost/type_traits/is_base_of.hpp>
2010-01-29 22:52:45 +02:00
# include <boost/type_traits/is_array.hpp>
# include <boost/type_traits/remove_pointer.hpp>
# include <boost/type_traits/remove_const.hpp>
2011-01-20 19:25:15 +02:00
# include <boost/unordered_set.hpp>
2009-04-16 14:14:13 +03:00
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/equal_to.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/identity.hpp>
2010-06-26 19:02:10 +03:00
# include <boost/any.hpp>
2009-04-16 14:14:13 +03:00
2010-12-17 20:47:07 +02:00
# include "ConstTransitivePtr.h"
2011-05-26 02:52:27 +03:00
const ui32 version = 729 ;
2009-04-16 14:14:13 +03:00
class CConnection ;
2009-10-06 03:32:33 +03:00
class CGObjectInstance ;
class CGameState ;
2010-05-02 21:20:26 +03:00
class CCreature ;
2010-06-26 19:02:10 +03:00
class LibClasses ;
class CHero ;
2010-10-31 00:53:41 +03:00
struct CPack ;
2010-06-26 19:02:10 +03:00
extern DLL_EXPORT LibClasses * VLC ;
2009-04-16 14:14:13 +03:00
namespace mpl = boost : : mpl ;
2009-04-15 17:03:31 +03:00
/*
* Connection . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
2009-04-16 14:14:13 +03:00
*/
namespace boost
{
namespace asio
{
namespace ip
{
class tcp ;
}
class io_service ;
template < typename Protocol > class stream_socket_service ;
template < typename Protocol , typename StreamSocketService >
class basic_stream_socket ;
template < typename Protocol > class socket_acceptor_service ;
template < typename Protocol , typename SocketAcceptorService >
class basic_socket_acceptor ;
}
class mutex ;
} ;
enum SerializationLvl
{
Wrong = 0 ,
Primitive ,
Array ,
Pointer ,
Serializable
} ;
struct TypeComparer
{
bool operator ( ) ( const std : : type_info * a , const std : : type_info * b ) const
{
return a - > before ( * b ) ;
}
} ;
class DLL_EXPORT CTypeList
{
typedef std : : multimap < const std : : type_info * , ui16 , TypeComparer > TTypeMap ;
2010-02-08 16:38:06 +02:00
TTypeMap types ;
2009-04-16 14:14:13 +03:00
public :
CTypeList ( ) ;
ui16 registerType ( const std : : type_info * type ) ;
template < typename T > ui16 registerType ( const T * t = NULL )
{
return registerType ( getTypeInfo ( t ) ) ;
}
ui16 getTypeID ( const std : : type_info * type ) ;
2011-07-17 21:49:05 +03:00
template < typename T > ui16 getTypeID ( const T * t = NULL )
2009-04-16 14:14:13 +03:00
{
return getTypeID ( getTypeInfo ( t ) ) ;
}
template < typename T > const std : : type_info * getTypeInfo ( const T * t = NULL )
{
if ( t )
return & typeid ( * t ) ;
else
return & typeid ( T ) ;
}
} ;
extern DLL_EXPORT CTypeList typeList ;
template < typename Ser , typename T >
struct SavePrimitive
{
static void invoke ( Ser & s , const T & data )
{
s . savePrimitive ( data ) ;
}
} ;
template < typename Ser , typename T >
struct SaveSerializable
{
static void invoke ( Ser & s , const T & data )
{
s . saveSerializable ( data ) ;
}
} ;
template < typename Ser , typename T >
struct LoadPrimitive
{
static void invoke ( Ser & s , T & data )
{
s . loadPrimitive ( data ) ;
}
} ;
template < typename Ser , typename T >
struct SavePointer
{
static void invoke ( Ser & s , const T & data )
{
s . savePointer ( data ) ;
}
} ;
template < typename Ser , typename T >
struct LoadPointer
{
static void invoke ( Ser & s , T & data )
{
s . loadPointer ( data ) ;
}
} ;
template < typename Ser , typename T >
struct SaveArray
{
static void invoke ( Ser & s , const T & data )
{
s . saveArray ( data ) ;
}
} ;
template < typename Ser , typename T >
struct LoadArray
{
static void invoke ( Ser & s , T & data )
{
s . loadArray ( data ) ;
}
} ;
template < typename Ser , typename T >
struct LoadSerializable
{
static void invoke ( Ser & s , T & data )
{
s . loadSerializable ( data ) ;
}
} ;
template < typename Ser , typename T >
struct SaveWrong
{
static void invoke ( Ser & s , const T & data )
{
throw std : : string ( " Wrong save serialization call! " ) ;
}
} ;
template < typename Ser , typename T >
struct LoadWrong
{
static void invoke ( Ser & s , const T & data )
{
throw std : : string ( " Wrong load serialization call! " ) ;
}
} ;
template < typename T >
struct SerializationLevel
{
typedef mpl : : integral_c_tag tag ;
typedef
typename mpl : : eval_if <
boost : : is_fundamental < T > ,
mpl : : int_ < Primitive > ,
//else
typename mpl : : eval_if <
boost : : is_class < T > ,
mpl : : int_ < Serializable > ,
//else
typename mpl : : eval_if <
boost : : is_array < T > ,
mpl : : int_ < Array > ,
//else
typename mpl : : eval_if <
boost : : is_pointer < T > ,
mpl : : int_ < Pointer > ,
//else
typename mpl : : eval_if <
boost : : is_enum < T > ,
mpl : : int_ < Primitive > ,
//else
mpl : : int_ < Wrong >
>
>
>
>
> : : type type ;
static const int value = SerializationLevel : : type : : value ;
} ;
2010-06-26 19:02:10 +03:00
template < typename T >
struct VectorisedObjectInfo
{
2010-12-17 20:47:07 +02:00
const std : : vector < ConstTransitivePtr < T > > * vector ; //pointer to the appropriate vector
2010-06-26 19:02:10 +03:00
const si32 T : : * idPtr ; //pointer to the field representing the position in the vector
2010-12-17 20:47:07 +02:00
VectorisedObjectInfo ( const std : : vector < ConstTransitivePtr < T > > * Vector , const si32 T : : * IdPtr )
2010-06-26 19:02:10 +03:00
: vector ( Vector ) , idPtr ( IdPtr )
{
}
} ;
2011-02-22 13:52:36 +02:00
/// Class which is responsible for storing and loading data.
2010-06-26 19:02:10 +03:00
class DLL_EXPORT CSerializer
{
public :
typedef std : : map < const std : : type_info * , boost : : any , TypeComparer > TTypeVecMap ;
TTypeVecMap vectors ; //entry must be a pointer to vector containing pointers to the objects of key type
bool smartVectorMembersSerialization ;
CSerializer ( ) ;
~ CSerializer ( ) ;
2010-07-14 05:53:21 +03:00
virtual void reportState ( CLogger & out ) { } ;
2010-06-26 19:02:10 +03:00
template < typename T >
void registerVectoredType ( const std : : vector < T * > * Vector , const si32 T : : * IdPtr )
{
vectors [ & typeid ( T ) ] = VectorisedObjectInfo < T > ( Vector , IdPtr ) ;
}
2010-12-17 20:47:07 +02:00
template < typename T >
void registerVectoredType ( const std : : vector < ConstTransitivePtr < T > > * Vector , const si32 T : : * IdPtr )
{
vectors [ & typeid ( T ) ] = VectorisedObjectInfo < T > ( Vector , IdPtr ) ;
}
2010-06-26 19:02:10 +03:00
template < typename T >
const VectorisedObjectInfo < T > * getVectorisedTypeInfo ( )
{
const std : : type_info * myType = NULL ;
//
// if(boost::is_base_of<CGObjectInstance, T>::value) //ugly workaround to support also types derived from CGObjectInstance -> if we encounter one, treat it aas CGObj..
// myType = &typeid(CGObjectInstance);
// else
myType = & typeid ( T ) ;
TTypeVecMap : : iterator i = vectors . find ( myType ) ;
if ( i = = vectors . end ( ) )
return NULL ;
else
{
assert ( ! i - > second . empty ( ) ) ;
assert ( i - > second . type ( ) = = typeid ( VectorisedObjectInfo < T > ) ) ;
VectorisedObjectInfo < T > * ret = & ( boost : : any_cast < VectorisedObjectInfo < T > & > ( i - > second ) ) ;
return ret ;
}
}
template < typename T >
2010-10-18 18:08:59 +03:00
T * getVectorItemFromId ( const VectorisedObjectInfo < T > & oInfo , ui32 id ) const
2010-06-26 19:02:10 +03:00
{
2010-10-18 18:08:59 +03:00
/* if(id < 0)
return NULL ; */
2010-06-26 19:02:10 +03:00
assert ( oInfo . vector ) ;
assert ( oInfo . vector - > size ( ) > id ) ;
2010-12-19 00:11:28 +02:00
return const_cast < T * > ( ( * oInfo . vector ) [ id ] . get ( ) ) ;
2010-06-26 19:02:10 +03:00
}
template < typename T >
si32 getIdFromVectorItem ( const VectorisedObjectInfo < T > & oInfo , const T * obj ) const
{
if ( ! obj )
return - 1 ;
return obj - > * oInfo . idPtr ;
}
void addStdVecItems ( CGameState * gs , LibClasses * lib = VLC ) ;
} ;
class DLL_EXPORT CSaverBase : public virtual CSerializer
2009-04-16 14:14:13 +03:00
{
} ;
class CBasicPointerSaver
{
public :
virtual void savePtr ( CSaverBase & ar , const void * data ) const = 0 ;
2009-12-31 13:04:29 +02:00
~ CBasicPointerSaver ( ) { }
2009-04-16 14:14:13 +03:00
} ;
template < typename Serializer , typename T > class CPointerSaver : public CBasicPointerSaver
{
public :
void savePtr ( CSaverBase & ar , const void * data ) const
{
Serializer & s = static_cast < Serializer & > ( ar ) ;
const T * ptr = static_cast < const T * > ( data ) ;
//T is most derived known type, it's time to call actual serialize
const_cast < T & > ( * ptr ) . serialize ( s , version ) ;
}
} ;
2010-06-26 19:02:10 +03:00
template < typename T > //metafunction returning CGObjectInstance if T is its derivate or T elsewise
struct VectorisedTypeFor
{
typedef typename
//if
mpl : : eval_if < boost : : is_base_of < CGObjectInstance , T > ,
mpl : : identity < CGObjectInstance > ,
//else
mpl : : identity < T >
> : : type type ;
} ;
2011-02-22 13:52:36 +02:00
/// The class which manages saving objects.
2009-04-16 14:14:13 +03:00
template < typename Serializer > class DLL_EXPORT COSer : public CSaverBase
{
public :
bool saving ;
std : : map < ui16 , CBasicPointerSaver * > savers ; // typeID => CPointerSaver<serializer,type>
2009-12-29 03:07:17 +02:00
std : : map < const void * , ui32 > savedPointers ;
bool smartPointerSerialization ;
2009-04-16 14:14:13 +03:00
COSer ( )
{
saving = true ;
2009-12-29 03:07:17 +02:00
smartPointerSerialization = true ;
2009-04-16 14:14:13 +03:00
}
2009-12-31 13:04:29 +02:00
~ COSer ( )
{
std : : map < ui16 , CBasicPointerSaver * > : : iterator iter ;
for ( iter = savers . begin ( ) ; iter ! = savers . end ( ) ; iter + + )
delete iter - > second ;
}
2009-04-16 14:14:13 +03:00
template < typename T > void registerType ( const T * t = NULL )
{
ui16 ID = typeList . registerType ( t ) ;
savers [ ID ] = new CPointerSaver < COSer < Serializer > , T > ;
}
Serializer * This ( )
{
return static_cast < Serializer * > ( this ) ;
}
template < class T >
Serializer & operator < < ( const T & t )
{
this - > This ( ) - > save ( t ) ;
return * this - > This ( ) ;
}
template < class T >
COSer & operator & ( const T & t )
{
return * this - > This ( ) < < t ;
}
int write ( const void * data , unsigned size ) ;
template < typename T >
void savePrimitive ( const T & data )
{
this - > This ( ) - > write ( & data , sizeof ( data ) ) ;
}
template < typename T >
void savePointer ( const T & data )
{
//write if pointer is not NULL
ui8 hlp = ( data ! = NULL ) ;
* this < < hlp ;
//if pointer is NULL then we don't need anything more...
if ( ! hlp )
return ;
2010-06-26 19:02:10 +03:00
if ( smartVectorMembersSerialization )
{
typedef typename boost : : remove_const < typename boost : : remove_pointer < T > : : type > : : type TObjectType ;
typedef typename VectorisedTypeFor < TObjectType > : : type VType ;
if ( const VectorisedObjectInfo < VType > * info = getVectorisedTypeInfo < VType > ( ) )
{
2010-12-26 16:34:11 +02:00
si32 id = getIdFromVectorItem < VType > ( * info , data ) ;
* this < < id ;
if ( id ! = - 1 ) //vector id is enough
return ;
2010-06-26 19:02:10 +03:00
}
}
2010-12-26 16:34:11 +02:00
2009-12-29 03:07:17 +02:00
if ( smartPointerSerialization )
{
std : : map < const void * , ui32 > : : iterator i = savedPointers . find ( data ) ;
if ( i ! = savedPointers . end ( ) )
{
//this pointer has been already serialized - write only it's id
* this < < i - > second ;
return ;
}
//give id to this pointer
ui32 pid = ( ui32 ) savedPointers . size ( ) ;
savedPointers [ data ] = pid ;
* this < < pid ;
}
2009-04-16 14:14:13 +03:00
//write type identifier
ui16 tid = typeList . getTypeID ( data ) ;
* this < < tid ;
2009-10-06 03:32:33 +03:00
This ( ) - > savePointerHlp ( tid , data ) ;
}
//that part of ptr serialization was extracted to allow customization of its behavior in derived classes
template < typename T >
void savePointerHlp ( ui16 tid , const T & data )
{
2009-04-16 14:14:13 +03:00
if ( ! tid )
* this < < * data ; //if type is unregistered simply write all data in a standard way
else
savers [ tid ] - > savePtr ( * this , data ) ; //call serializer specific for our real type
}
template < typename T >
void saveArray ( const T & data )
{
ui32 size = ARRAY_COUNT ( data ) ;
for ( ui32 i = 0 ; i < size ; i + + )
* this < < data [ i ] ;
}
template < typename T >
void save ( const T & data )
{
typedef
//if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Primitive > > ,
mpl : : identity < SavePrimitive < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Pointer > > ,
mpl : : identity < SavePointer < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Array > > ,
mpl : : identity < SaveArray < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Serializable > > ,
mpl : : identity < SaveSerializable < Serializer , T > > ,
//else
mpl : : identity < SaveWrong < Serializer , T > >
>
>
>
> : : type typex ;
typex : : invoke ( * this - > This ( ) , data ) ;
}
template < typename T >
void saveSerializable ( const T & data )
{
const_cast < T & > ( data ) . serialize ( * this , version ) ;
}
template < typename T >
2010-11-20 02:03:31 +02:00
void saveSerializable ( const boost : : shared_ptr < T > & data )
{
T * internalPtr = data . get ( ) ;
* this < < internalPtr ;
}
template < typename T >
2009-04-16 14:14:13 +03:00
void saveSerializable ( const std : : vector < T > & data )
{
boost : : uint32_t length = data . size ( ) ;
* this < < length ;
for ( ui32 i = 0 ; i < length ; i + + )
* this < < data [ i ] ;
}
template < typename T >
void saveSerializable ( const std : : set < T > & data )
{
std : : set < T > & d = const_cast < std : : set < T > & > ( data ) ;
boost : : uint32_t length = d . size ( ) ;
* this < < length ;
for ( typename std : : set < T > : : iterator i = d . begin ( ) ; i ! = d . end ( ) ; i + + )
* this < < * i ;
}
2011-01-20 19:25:15 +02:00
template < typename T , typename U >
void saveSerializable ( const boost : : unordered_set < T , U > & data )
{
boost : : unordered_set < T , U > & d = const_cast < boost : : unordered_set < T , U > & > ( data ) ;
boost : : uint32_t length = d . size ( ) ;
* this < < length ;
for ( typename boost : : unordered_set < T , U > : : iterator i = d . begin ( ) ; i ! = d . end ( ) ; i + + )
* this < < * i ;
}
2009-04-16 14:14:13 +03:00
template < typename T >
void saveSerializable ( const std : : list < T > & data )
{
std : : list < T > & d = const_cast < std : : list < T > & > ( data ) ;
boost : : uint32_t length = d . size ( ) ;
* this < < length ;
for ( typename std : : list < T > : : iterator i = d . begin ( ) ; i ! = d . end ( ) ; i + + )
* this < < * i ;
}
void saveSerializable ( const std : : string & data )
{
* this < < ui32 ( data . length ( ) ) ;
this - > This ( ) - > write ( data . c_str ( ) , data . size ( ) ) ;
}
template < typename T1 , typename T2 >
void saveSerializable ( const std : : pair < T1 , T2 > & data )
{
* this < < data . first < < data . second ;
}
template < typename T1 , typename T2 >
void saveSerializable ( const std : : map < T1 , T2 > & data )
{
* this < < ui32 ( data . size ( ) ) ;
for ( typename std : : map < T1 , T2 > : : const_iterator i = data . begin ( ) ; i ! = data . end ( ) ; i + + )
* this < < i - > first < < i - > second ;
}
} ;
2010-06-26 19:02:10 +03:00
class DLL_EXPORT CLoaderBase : public virtual CSerializer
2009-04-16 14:14:13 +03:00
{ } ;
class CBasicPointerLoader
{
public :
2010-05-15 05:26:49 +03:00
virtual void loadPtr ( CLoaderBase & ar , void * data , ui32 pid ) const = 0 ; //data is pointer to the ACTUAL POINTER
2009-12-31 13:04:29 +02:00
virtual ~ CBasicPointerLoader ( ) { }
2009-04-16 14:14:13 +03:00
} ;
template < typename Serializer , typename T > class CPointerLoader : public CBasicPointerLoader
{
public :
2010-05-15 05:26:49 +03:00
void loadPtr ( CLoaderBase & ar , void * data , ui32 pid ) const //data is pointer to the ACTUAL POINTER
2009-04-16 14:14:13 +03:00
{
Serializer & s = static_cast < Serializer & > ( ar ) ;
T * & ptr = * static_cast < T * * > ( data ) ;
//create new object under pointer
typedef typename boost : : remove_pointer < T > : : type npT ;
ptr = new npT ;
2010-05-15 05:26:49 +03:00
s . ptrAllocated ( ptr , pid ) ;
2009-04-16 14:14:13 +03:00
//T is most derived known type, it's time to call actual serialize
ptr - > serialize ( s , version ) ;
}
} ;
2011-02-22 13:52:36 +02:00
/// The class which manages loading of objects.
2009-04-16 14:14:13 +03:00
template < typename Serializer > class DLL_EXPORT CISer : public CLoaderBase
{
public :
bool saving ;
std : : map < ui16 , CBasicPointerLoader * > loaders ; // typeID => CPointerSaver<serializer,type>
2009-06-02 01:31:11 +03:00
ui32 myVersion ;
2009-04-16 14:14:13 +03:00
2009-12-29 03:07:17 +02:00
std : : map < ui32 , void * > loadedPointers ;
bool smartPointerSerialization ;
2009-04-16 14:14:13 +03:00
CISer ( )
{
saving = false ;
2009-06-02 01:31:11 +03:00
myVersion = version ;
2009-12-29 03:07:17 +02:00
smartPointerSerialization = true ;
2009-04-16 14:14:13 +03:00
}
2009-10-24 18:54:08 +03:00
~ CISer ( )
{
std : : map < ui16 , CBasicPointerLoader * > : : iterator iter ;
for ( iter = loaders . begin ( ) ; iter ! = loaders . end ( ) ; iter + + )
delete iter - > second ;
}
2009-04-16 14:14:13 +03:00
template < typename T > void registerType ( const T * t = NULL )
{
ui16 ID = typeList . registerType ( t ) ;
loaders [ ID ] = new CPointerLoader < CISer < Serializer > , T > ;
}
Serializer * This ( )
{
return static_cast < Serializer * > ( this ) ;
}
template < class T >
Serializer & operator > > ( T & t )
{
this - > This ( ) - > load ( t ) ;
return * this - > This ( ) ;
}
template < class T >
CISer & operator & ( T & t )
{
return * this - > This ( ) > > t ;
}
int write ( const void * data , unsigned size ) ;
template < typename T >
void load ( T & data )
{
typedef
//if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Primitive > > ,
mpl : : identity < LoadPrimitive < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Pointer > > ,
mpl : : identity < LoadPointer < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Array > > ,
mpl : : identity < LoadArray < Serializer , T > > ,
//else if
typename mpl : : eval_if < mpl : : equal_to < SerializationLevel < T > , mpl : : int_ < Serializable > > ,
mpl : : identity < LoadSerializable < Serializer , T > > ,
//else
mpl : : identity < LoadWrong < Serializer , T > >
>
>
>
> : : type typex ;
typex : : invoke ( * this - > This ( ) , data ) ;
}
template < typename T >
void loadPrimitive ( T & data )
{
this - > This ( ) - > read ( & data , sizeof ( data ) ) ;
}
template < typename T >
void loadSerializable ( T & data )
{
2010-01-29 22:52:45 +02:00
////that const cast is evil because it allows to implicitly overwrite const objects when deserializing
typedef typename boost : : remove_const < T > : : type nonConstT ;
nonConstT & hlp = const_cast < nonConstT & > ( data ) ;
hlp . serialize ( * this , myVersion ) ;
//data.serialize(*this,myVersion);
2009-04-16 14:14:13 +03:00
}
template < typename T >
void loadArray ( T & data )
{
ui32 size = ARRAY_COUNT ( data ) ;
for ( ui32 i = 0 ; i < size ; i + + )
* this > > data [ i ] ;
}
template < typename T >
void loadPointer ( T & data )
{
ui8 hlp ;
* this > > hlp ;
if ( ! hlp )
{
data = NULL ;
return ;
}
2010-06-26 19:02:10 +03:00
if ( smartVectorMembersSerialization )
{
typedef typename boost : : remove_const < typename boost : : remove_pointer < T > : : type > : : type TObjectType ; //eg: const CGHeroInstance * => CGHeroInstance
typedef typename VectorisedTypeFor < TObjectType > : : type VType ; //eg: CGHeroInstance -> CGobjectInstance
if ( const VectorisedObjectInfo < VType > * info = getVectorisedTypeInfo < VType > ( ) )
{
2010-12-26 16:34:11 +02:00
si32 id ;
2010-06-26 19:02:10 +03:00
* this > > id ;
2010-12-26 16:34:11 +02:00
if ( id ! = - 1 )
{
data = static_cast < T > ( getVectorItemFromId ( * info , id ) ) ;
return ;
}
2010-06-26 19:02:10 +03:00
}
}
2009-04-16 14:14:13 +03:00
2010-10-18 18:08:59 +03:00
ui32 pid = 0xffffffff ; //pointer id (or maybe rather pointee id)
2009-12-29 03:07:17 +02:00
if ( smartPointerSerialization )
{
* this > > pid ; //get the id
2010-05-15 05:26:49 +03:00
std : : map < ui32 , void * > : : iterator i = loadedPointers . find ( pid ) ; //lookup
2009-12-29 03:07:17 +02:00
if ( i ! = loadedPointers . end ( ) )
{
//we already got this pointer
data = static_cast < T > ( i - > second ) ;
return ;
}
}
2009-04-16 14:14:13 +03:00
//get type id
ui16 tid ;
* this > > tid ;
2010-05-15 05:26:49 +03:00
This ( ) - > loadPointerHlp ( tid , data , pid ) ;
2009-10-06 03:32:33 +03:00
}
2009-04-16 14:14:13 +03:00
2009-10-06 03:32:33 +03:00
//that part of ptr deserialization was extracted to allow customization of its behavior in derived classes
template < typename T >
2010-05-15 05:26:49 +03:00
void loadPointerHlp ( ui16 tid , T & data , ui32 pid )
2009-10-06 03:32:33 +03:00
{
2009-04-16 14:14:13 +03:00
if ( ! tid )
{
typedef typename boost : : remove_pointer < T > : : type npT ;
2010-01-29 22:52:45 +02:00
typedef typename boost : : remove_const < npT > : : type ncpT ;
data = new ncpT ;
2010-05-15 05:26:49 +03:00
ptrAllocated ( data , pid ) ;
2009-04-16 14:14:13 +03:00
* this > > * data ;
}
else
{
2010-05-15 05:26:49 +03:00
loaders [ tid ] - > loadPtr ( * this , & data , pid ) ;
2009-04-16 14:14:13 +03:00
}
}
2009-10-06 03:32:33 +03:00
2010-05-15 05:26:49 +03:00
template < typename T >
void ptrAllocated ( const T * ptr , ui32 pid )
{
2010-10-18 18:08:59 +03:00
if ( smartPointerSerialization & & pid ! = 0xffffffff )
2010-05-15 05:26:49 +03:00
loadedPointers [ pid ] = ( void * ) ptr ; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
}
2010-07-14 05:53:21 +03:00
# define READ_CHECK_U32(x) \
boost : : uint32_t length ; \
* this > > length ; \
if ( length > 50000 ) \
{ \
tlog2 < < " Warning: very big length: " < < length < < " \n " ; \
reportState ( tlog2 ) ; \
} ;
2010-11-20 02:03:31 +02:00
template < typename T >
void loadSerializable ( boost : : shared_ptr < T > & data )
{
T * internalPtr ;
* this > > internalPtr ;
data . reset ( internalPtr ) ;
}
2009-04-16 14:14:13 +03:00
template < typename T >
void loadSerializable ( std : : vector < T > & data )
{
2010-07-14 05:53:21 +03:00
READ_CHECK_U32 ( length ) ;
2009-04-16 14:14:13 +03:00
data . resize ( length ) ;
for ( ui32 i = 0 ; i < length ; i + + )
* this > > data [ i ] ;
}
template < typename T >
void loadSerializable ( std : : set < T > & data )
{
2010-07-14 05:53:21 +03:00
READ_CHECK_U32 ( length ) ;
2009-04-16 14:14:13 +03:00
T ins ;
for ( ui32 i = 0 ; i < length ; i + + )
{
* this > > ins ;
data . insert ( ins ) ;
}
}
2011-01-20 19:25:15 +02:00
template < typename T , typename U >
void loadSerializable ( boost : : unordered_set < T , U > & data )
{
READ_CHECK_U32 ( length ) ;
T ins ;
for ( ui32 i = 0 ; i < length ; i + + )
{
* this > > ins ;
data . insert ( ins ) ;
}
}
2009-04-16 14:14:13 +03:00
template < typename T >
void loadSerializable ( std : : list < T > & data )
{
2010-07-14 05:53:21 +03:00
READ_CHECK_U32 ( length ) ;
2009-04-16 14:14:13 +03:00
T ins ;
for ( ui32 i = 0 ; i < length ; i + + )
{
* this > > ins ;
data . push_back ( ins ) ;
}
}
template < typename T1 , typename T2 >
void loadSerializable ( std : : pair < T1 , T2 > & data )
{
* this > > data . first > > data . second ;
}
template < typename T1 , typename T2 >
void loadSerializable ( std : : map < T1 , T2 > & data )
{
2010-07-14 05:53:21 +03:00
READ_CHECK_U32 ( length ) ;
2009-04-16 14:14:13 +03:00
T1 t ;
2009-05-07 08:01:45 +03:00
for ( ui32 i = 0 ; i < length ; i + + )
2009-04-16 14:14:13 +03:00
{
* this > > t ;
* this > > data [ t ] ;
}
}
void loadSerializable ( std : : string & data )
{
2010-07-14 05:53:21 +03:00
READ_CHECK_U32 ( length ) ;
2009-04-16 14:14:13 +03:00
data . resize ( length ) ;
this - > This ( ) - > read ( ( void * ) data . c_str ( ) , length ) ;
}
} ;
class DLL_EXPORT CSaveFile
: public COSer < CSaveFile >
{
void dummyMagicFunction ( )
{
* this < < std : : string ( " This function makes stuff working. " ) ;
}
public :
2010-07-14 05:53:21 +03:00
std : : string fName ;
2009-04-16 14:14:13 +03:00
std : : ofstream * sfile ;
2010-07-14 05:53:21 +03:00
2009-04-16 14:14:13 +03:00
CSaveFile ( const std : : string & fname ) ;
~ CSaveFile ( ) ;
int write ( const void * data , unsigned size ) ;
2010-02-26 13:18:09 +02:00
void close ( ) ;
void openNextFile ( const std : : string & fname ) ;
2010-07-14 05:53:21 +03:00
void reportState ( CLogger & out ) ;
2009-04-16 14:14:13 +03:00
} ;
class DLL_EXPORT CLoadFile
: public CISer < CLoadFile >
{
void dummyMagicFunction ( )
{
std : : string dummy = " This function makes stuff working. " ;
* this > > dummy ;
}
public :
2010-07-14 05:53:21 +03:00
std : : string fName ;
2009-04-16 14:14:13 +03:00
std : : ifstream * sfile ;
2010-07-14 05:53:21 +03:00
2010-10-24 14:35:14 +03:00
CLoadFile ( const std : : string & fname , int minimalVersion = version ) ;
2009-04-16 14:14:13 +03:00
~ CLoadFile ( ) ;
int read ( const void * data , unsigned size ) ;
2010-02-26 13:18:09 +02:00
void close ( ) ;
2010-10-24 14:35:14 +03:00
void openNextFile ( const std : : string & fname , int minimalVersion ) ;
2010-07-14 05:53:21 +03:00
void reportState ( CLogger & out ) ;
2009-04-16 14:14:13 +03:00
} ;
2010-05-15 05:26:49 +03:00
typedef boost : : asio : : basic_stream_socket < boost : : asio : : ip : : tcp , boost : : asio : : stream_socket_service < boost : : asio : : ip : : tcp > > TSocket ;
typedef boost : : asio : : basic_socket_acceptor < boost : : asio : : ip : : tcp , boost : : asio : : socket_acceptor_service < boost : : asio : : ip : : tcp > > TAcceptor ;
2009-04-16 14:14:13 +03:00
class DLL_EXPORT CConnection
: public CISer < CConnection > , public COSer < CConnection >
{
2010-06-26 19:02:10 +03:00
//CGameState *gs;
2009-04-16 14:14:13 +03:00
CConnection ( void ) ;
2009-10-06 03:32:33 +03:00
2009-04-16 14:14:13 +03:00
void init ( ) ;
2010-07-14 05:53:21 +03:00
void reportState ( CLogger & out ) ;
2009-04-16 14:14:13 +03:00
public :
boost : : mutex * rmx , * wmx ; // read/write mutexes
2010-05-15 05:26:49 +03:00
TSocket * socket ;
2009-04-16 14:14:13 +03:00
bool logging ;
bool connected ;
bool myEndianess , contactEndianess ; //true if little endian, if ednianess is different we'll have to revert recieved multi-byte vars
boost : : asio : : io_service * io_service ;
std : : string name ; //who uses this connection
2010-10-24 14:35:14 +03:00
int connectionID ;
CConnection * c ;
boost : : thread * handler ;
bool receivedStop , sendStop ;
2010-05-15 05:26:49 +03:00
CConnection ( std : : string host , std : : string port , std : : string Name ) ;
CConnection ( TAcceptor * acceptor , boost : : asio : : io_service * Io_service , std : : string Name ) ;
CConnection ( TSocket * Socket , std : : string Name ) ; //use immediately after accepting connection into socket
2009-04-16 14:14:13 +03:00
int write ( const void * data , unsigned size ) ;
int read ( void * data , unsigned size ) ;
void close ( ) ;
2010-01-29 22:52:45 +02:00
bool isOpen ( ) const ;
2009-04-16 14:14:13 +03:00
template < class T >
CConnection & operator & ( const T & ) ;
~ CConnection ( void ) ;
2010-09-03 21:42:54 +03:00
CPack * retreivePack ( ) ; //gets from server next pack (allocates it with new)
2011-08-25 18:24:37 +03:00
void sendPack ( const CPack & pack ) ;
2010-09-03 21:42:54 +03:00
} ;
2010-10-24 14:35:14 +03:00
DLL_EXPORT std : : ostream & operator < < ( std : : ostream & str , const CConnection & cpc ) ;
2010-09-03 21:42:54 +03:00
template < typename T >
class CApplier
{
public :
std : : map < ui16 , T * > apps ;
~ CApplier ( )
{
2010-09-04 17:47:39 +03:00
typename std : : map < ui16 , T * > : : iterator iter ;
2010-09-03 21:42:54 +03:00
for ( iter = apps . begin ( ) ; iter ! = apps . end ( ) ; iter + + )
delete iter - > second ;
}
template < typename U > void registerType ( const U * t = NULL )
{
ui16 ID = typeList . registerType ( t ) ;
apps [ ID ] = T : : getApplier ( t ) ;
}
2009-04-16 14:14:13 +03:00
} ;
2011-02-04 16:58:14 +02:00
2009-04-16 14:14:13 +03:00
# endif // __CONNECTION_H__