Init
This commit is contained in:
712
DependentExtensions/RPC3/RPC3_Boost.h
Normal file
712
DependentExtensions/RPC3/RPC3_Boost.h
Normal file
@ -0,0 +1,712 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2017-2020, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#ifndef __RPC3_BOOST_H
|
||||
#define __RPC3_BOOST_H
|
||||
|
||||
// Fixes
|
||||
// error C2504: 'boost::fusion::detail::invoke_impl<Function,Sequence,N,CBI,RandomAccess>' : base class undefined
|
||||
// This defines the maximum number of parameters you can have
|
||||
#ifndef BOOST_FUSION_INVOKE_MAX_ARITY
|
||||
#define BOOST_FUSION_INVOKE_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
// Boost dependencies
|
||||
// Boost is assumed to be at C:\boost_1_43_0 based on the project settings
|
||||
// If this is not where you downloaded boost, change the project settings Configuration Properties / C/C++ / General / Additional Include Directories
|
||||
// If you don't have boost, get it from http://www.boost.org/users/download/
|
||||
// If you don't want to use boost, use RPC4 instead which relies on assembly but has fewer features
|
||||
#include "boost/type_traits.hpp"
|
||||
#include "boost/function.hpp"
|
||||
#include "boost/bind.hpp"
|
||||
#include "boost/mpl/if.hpp"
|
||||
#include "boost/mpl/apply.hpp"
|
||||
#include "boost/function_types/parameter_types.hpp"
|
||||
#include "boost/fusion/container/list/cons.hpp" // boost::fusion::nil
|
||||
#include "boost/fusion/include/push_back.hpp"
|
||||
#include "boost/fusion/include/invoke.hpp"
|
||||
#include "boost/fusion/tuple/tuple.hpp"
|
||||
#include "boost/fusion/tuple/make_tuple.hpp"
|
||||
#include "boost/fusion/functional/invocation/invoke.hpp"
|
||||
#include "boost/type_traits/is_array.hpp"
|
||||
|
||||
// Not needed?
|
||||
//#include <boost/fusion/container/generation/make_vector.hpp>
|
||||
|
||||
#include "slikenet/NetworkIDManager.h"
|
||||
#include "slikenet/NetworkIDObject.h"
|
||||
#include "slikenet/BitStream.h"
|
||||
|
||||
namespace SLNet
|
||||
{
|
||||
class RPC3;
|
||||
class BitStream;
|
||||
|
||||
|
||||
namespace _RPC3
|
||||
{
|
||||
|
||||
enum InvokeResultCodes
|
||||
{
|
||||
IRC_SUCCESS,
|
||||
IRC_NEED_BITSTREAM,
|
||||
IRC_NEED_NETWORK_ID_MANAGER,
|
||||
IRC_NEED_NETWORK_ID,
|
||||
IRC_NEED_CLASS_OBJECT,
|
||||
};
|
||||
|
||||
struct InvokeArgs
|
||||
{
|
||||
// Bitstream to use to deserialize
|
||||
SLNet::BitStream *bitStream;
|
||||
|
||||
// NetworkIDManager to use to lookup objects
|
||||
NetworkIDManager *networkIDManager;
|
||||
|
||||
// C++ class member object
|
||||
NetworkID classMemberObjectId;
|
||||
|
||||
// The calling plugin
|
||||
RPC3 *caller;
|
||||
|
||||
// The this pointer for C++
|
||||
NetworkIDObject *thisPtr;
|
||||
};
|
||||
|
||||
typedef boost::fusion::tuple<bool, boost::function<InvokeResultCodes (InvokeArgs)> > FunctionPointer;
|
||||
|
||||
struct StrWithDestructor
|
||||
{
|
||||
char *c;
|
||||
~StrWithDestructor() {if (c) delete c;}
|
||||
};
|
||||
|
||||
enum RPC3TagFlag
|
||||
{
|
||||
RPC3_TAG_FLAG_DEREF=1,
|
||||
RPC3_TAG_FLAG_ARRAY=2,
|
||||
};
|
||||
|
||||
struct RPC3Tag
|
||||
{
|
||||
RPC3Tag() {}
|
||||
RPC3Tag(void *_v, unsigned int _count, RPC3TagFlag _flag) : v(_v), count(_count), flag((unsigned char)_flag) {}
|
||||
void* v;
|
||||
unsigned int count;
|
||||
unsigned char flag;
|
||||
};
|
||||
|
||||
// Track the pointers tagged with SLNet::_RPC3::Deref
|
||||
static RPC3Tag __RPC3TagPtrs[BOOST_FUSION_INVOKE_MAX_ARITY+1];
|
||||
static int __RPC3TagHead=0;
|
||||
static int __RPC3TagTail=0;
|
||||
|
||||
// If this assert hits, then SLNet::_RPC3::Deref was called more times than the argument was passed to the function
|
||||
static void __RPC3_Tag_AddHead(const RPC3Tag &p)
|
||||
{
|
||||
// Update tag if already in array
|
||||
int i;
|
||||
for (i=__RPC3TagTail; i!=__RPC3TagHead; i=(i+1)%BOOST_FUSION_INVOKE_MAX_ARITY)
|
||||
{
|
||||
if (__RPC3TagPtrs[i].v==p.v)
|
||||
{
|
||||
if (p.flag==RPC3_TAG_FLAG_ARRAY)
|
||||
{
|
||||
__RPC3TagPtrs[i].count=p.count;
|
||||
}
|
||||
__RPC3TagPtrs[i].flag|=p.flag;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
__RPC3TagPtrs[__RPC3TagHead]=p;
|
||||
__RPC3TagHead = (__RPC3TagHead + 1) % BOOST_FUSION_INVOKE_MAX_ARITY;
|
||||
assert(__RPC3TagHead!=__RPC3TagTail);
|
||||
}
|
||||
static void __RPC3ClearTail(void) {
|
||||
while (__RPC3TagTail!=__RPC3TagHead)
|
||||
{
|
||||
if (__RPC3TagPtrs[__RPC3TagTail].v==0)
|
||||
__RPC3TagTail = (__RPC3TagTail+1) % BOOST_FUSION_INVOKE_MAX_ARITY;
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
static bool __RPC3ClearPtr(void* p, RPC3Tag *tag) {
|
||||
int i;
|
||||
for (i=__RPC3TagTail; i!=__RPC3TagHead; i=(i+1)%BOOST_FUSION_INVOKE_MAX_ARITY)
|
||||
{
|
||||
if (__RPC3TagPtrs[i].v==p)
|
||||
{
|
||||
*tag=__RPC3TagPtrs[i];
|
||||
__RPC3TagPtrs[i].v=0;
|
||||
__RPC3ClearTail();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tag->flag=0;
|
||||
tag->count=1;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class templateType>
|
||||
inline const templateType& Deref(const templateType & t) {
|
||||
__RPC3_Tag_AddHead(RPC3Tag((void*)t,1,RPC3_TAG_FLAG_DEREF));
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class templateType>
|
||||
inline const templateType& PtrToArray(unsigned int count, const templateType & t) {
|
||||
__RPC3_Tag_AddHead(RPC3Tag((void*)t,count,RPC3_TAG_FLAG_ARRAY));
|
||||
return t;
|
||||
}
|
||||
|
||||
struct ReadBitstream
|
||||
{
|
||||
static void applyArray(SLNet::BitStream &bitStream, SLNet::BitStream* t){apply(bitStream,t);}
|
||||
|
||||
static void apply(SLNet::BitStream &bitStream, SLNet::BitStream* t)
|
||||
{
|
||||
BitSize_t numBitsUsed;
|
||||
bitStream.ReadCompressed(numBitsUsed);
|
||||
bitStream.Read(t,numBitsUsed);
|
||||
}
|
||||
};
|
||||
|
||||
//template <typename T>
|
||||
struct ReadPtr
|
||||
{
|
||||
template <typename T2>
|
||||
static inline void applyArray(SLNet::BitStream &bitStream, T2 *t) {bitStream >> (*t);}
|
||||
template <typename T2>
|
||||
static inline void apply(SLNet::BitStream &bitStream, T2 *t) {bitStream >> (*t);}
|
||||
|
||||
static inline void apply(SLNet::BitStream &bitStream, char *&t) {applyStr(bitStream, (char *&) t);}
|
||||
static inline void apply(SLNet::BitStream &bitStream, unsigned char *&t) {applyStr(bitStream, (char *&) t);}
|
||||
static inline void apply(SLNet::BitStream &bitStream, const char *&t) {applyStr(bitStream, (char *&) t);}
|
||||
static inline void apply(SLNet::BitStream &bitStream, const unsigned char *&t) {applyStr(bitStream, (char *&) t);}
|
||||
static inline void applyStr(SLNet::BitStream &bitStream, char *&t)
|
||||
{
|
||||
SLNet::RakString rs;
|
||||
bitStream >> rs;
|
||||
size_t len = rs.GetLength()+1;
|
||||
|
||||
// The caller should have already allocated memory, so we need to free
|
||||
// it and allocate a new buffer.
|
||||
RakAssert("Expected allocated array, got a null pointer" && (nullptr != t));
|
||||
delete [] t;
|
||||
|
||||
t = new char [len];
|
||||
memcpy(t,rs.C_String(),len);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< typename T >
|
||||
struct DoRead
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_convertible<T*, SLNet::BitStream*>,
|
||||
ReadBitstream,
|
||||
ReadPtr >::type type;
|
||||
};
|
||||
|
||||
|
||||
template< typename T >
|
||||
struct ReadWithoutNetworkIDNoPtr
|
||||
{
|
||||
static InvokeResultCodes apply(InvokeArgs &args, T &t)
|
||||
{
|
||||
// printf("ReadWithoutNetworkIDNoPtr\n");
|
||||
|
||||
DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),&t);
|
||||
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
// typedef boost::mpl::false_ Cleanup;
|
||||
template< typename T2 >
|
||||
static void Cleanup(T2 &t)
|
||||
{
|
||||
// unused parameters
|
||||
(void)t;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct ReadWithNetworkIDPtr
|
||||
{
|
||||
static InvokeResultCodes apply(InvokeArgs &args, T &t)
|
||||
{
|
||||
// printf("ReadWithNetworkIDPtr\n");
|
||||
// Read the network ID
|
||||
|
||||
bool isNull;
|
||||
args.bitStream->Read(isNull);
|
||||
if (isNull)
|
||||
{
|
||||
t=0;
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
bool deref, isArray;
|
||||
args.bitStream->Read(deref);
|
||||
args.bitStream->Read(isArray);
|
||||
unsigned int count;
|
||||
if (isArray)
|
||||
args.bitStream->ReadCompressed(count);
|
||||
else
|
||||
count=1;
|
||||
NetworkID networkId;
|
||||
for (unsigned int i=0; i < count; i++)
|
||||
{
|
||||
args.bitStream->Read(networkId);
|
||||
t = args.networkIDManager->GET_OBJECT_FROM_ID< T >(networkId);
|
||||
if (deref)
|
||||
{
|
||||
BitSize_t bitsUsed;
|
||||
args.bitStream->AlignReadToByteBoundary();
|
||||
args.bitStream->Read(bitsUsed);
|
||||
|
||||
if (t)
|
||||
{
|
||||
DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip data!
|
||||
args.bitStream->IgnoreBits(bitsUsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
template< typename T2 >
|
||||
static void Cleanup(T2 &t)
|
||||
{
|
||||
// unused parameters
|
||||
(void)t;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct ReadWithoutNetworkIDPtr
|
||||
{
|
||||
template <typename T2>
|
||||
static InvokeResultCodes apply(InvokeArgs &args, T2 &t)
|
||||
{
|
||||
// printf("ReadWithoutNetworkIDPtr\n");
|
||||
|
||||
bool isNull=false;
|
||||
args.bitStream->Read(isNull);
|
||||
if (isNull)
|
||||
{
|
||||
t=0;
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
typedef typename boost::remove_pointer< T >::type ActualObjectType;
|
||||
|
||||
bool isArray=false;
|
||||
unsigned int count;
|
||||
args.bitStream->Read(isArray);
|
||||
if (isArray)
|
||||
args.bitStream->ReadCompressed(count);
|
||||
else
|
||||
count=1;
|
||||
|
||||
t = new ActualObjectType[count]();
|
||||
if (isArray)
|
||||
{
|
||||
for (unsigned int i=0; i < count; i++)
|
||||
{
|
||||
DoRead< typename boost::remove_pointer<T>::type >::type::applyArray(* (args.bitStream),t+i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),t);
|
||||
}
|
||||
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
template< typename T2 >
|
||||
static void Cleanup(T2 &t)
|
||||
{
|
||||
if (t)
|
||||
delete [] t;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct SetRPC3Ptr
|
||||
{
|
||||
static InvokeResultCodes apply(InvokeArgs &args, T &obj)
|
||||
{
|
||||
obj=args.caller;
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
|
||||
//typedef boost::mpl::false_ Cleanup;
|
||||
template< typename T2 >
|
||||
static void Cleanup(T2 &t)
|
||||
{
|
||||
// unused parameters
|
||||
(void)t;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
template< typename T >
|
||||
struct ReadWithNetworkID
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_pointer<T>
|
||||
, typename ReadWithNetworkIDPtr<T> // true
|
||||
, typename ReadWithNetworkIDNoPtr<T>
|
||||
>::type type;
|
||||
};
|
||||
*/
|
||||
|
||||
template< typename T >
|
||||
struct ReadWithoutNetworkID
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_pointer<T>
|
||||
, ReadWithoutNetworkIDPtr<T> // true
|
||||
, ReadWithoutNetworkIDNoPtr<T>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct identity
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct IsRPC3Ptr
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_convertible<T,RPC3*>,
|
||||
boost::mpl::true_,
|
||||
boost::mpl::false_>::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct ShouldReadNetworkID
|
||||
{
|
||||
/*
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_pointer<T>,
|
||||
typename identity<T>::type,
|
||||
boost::add_pointer<T>>::type typeWithPtr;
|
||||
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_convertible<typeWithPtr,NetworkIDObject*>,
|
||||
boost::mpl::true_,
|
||||
boost::mpl::false_>::type type;
|
||||
*/
|
||||
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_convertible<T,NetworkIDObject*>,
|
||||
boost::mpl::true_,
|
||||
boost::mpl::false_>::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct GetReadFunction
|
||||
{
|
||||
/*
|
||||
typedef typename boost::mpl::if_<
|
||||
typename ShouldReadNetworkID<T>::type
|
||||
, typename ReadWithNetworkID<T>::type
|
||||
, typename ReadWithoutNetworkID<T>::type
|
||||
>::type type;
|
||||
*/
|
||||
|
||||
typedef typename boost::mpl::if_<
|
||||
typename ShouldReadNetworkID<T>::type
|
||||
, ReadWithNetworkIDPtr<T>
|
||||
, typename ReadWithoutNetworkID<T>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct ProcessArgType
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
typename IsRPC3Ptr<T>::type
|
||||
, SetRPC3Ptr<T>
|
||||
, typename GetReadFunction<T>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template< typename Function
|
||||
, class From = typename boost::mpl::begin< boost::function_types::parameter_types<Function> >::type
|
||||
, class To = typename boost::mpl::end< boost::function_types::parameter_types<Function> >::type
|
||||
>
|
||||
struct BoostRPCInvoker
|
||||
{
|
||||
// add an argument to a Fusion cons-list for each parameter type
|
||||
template<typename Args>
|
||||
static inline
|
||||
InvokeResultCodes apply(Function func, InvokeArgs &functionArgs, Args const &args)
|
||||
{
|
||||
typedef typename boost::mpl::deref<From>::type arg_type;
|
||||
typedef typename boost::mpl::next<From>::type next_iter_type;
|
||||
typedef typename boost::remove_reference<arg_type>::type arg_type_no_ref;
|
||||
|
||||
arg_type_no_ref argType;
|
||||
ProcessArgType< arg_type_no_ref >::type::apply(functionArgs, argType);
|
||||
|
||||
InvokeResultCodes irc = BoostRPCInvoker<Function, next_iter_type, To>::apply
|
||||
( func, functionArgs, boost::fusion::push_back(args, boost::ref(argType) ) );
|
||||
|
||||
ProcessArgType< arg_type_no_ref >::type::Cleanup(argType);
|
||||
return irc;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Function
|
||||
, class From = typename boost::mpl::begin< boost::function_types::parameter_types<Function> >::type
|
||||
, class To = typename boost::mpl::end< boost::function_types::parameter_types<Function> >::type
|
||||
>
|
||||
struct BoostRPCInvoker_ThisPtr
|
||||
{
|
||||
// add an argument to a Fusion cons-list for each parameter type
|
||||
template<typename Args>
|
||||
static inline
|
||||
InvokeResultCodes apply(Function func, InvokeArgs &functionArgs, Args const &args)
|
||||
{
|
||||
typedef typename boost::mpl::deref<From>::type arg_type;
|
||||
typedef typename boost::mpl::next<From>::type next_iter_type;
|
||||
|
||||
arg_type argType = (arg_type) *(functionArgs.thisPtr);
|
||||
|
||||
return BoostRPCInvoker<Function, next_iter_type, To>::apply
|
||||
( func, functionArgs, boost::fusion::push_back(args, boost::ref(argType) ) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Function, class To>
|
||||
struct BoostRPCInvoker<Function,To,To>
|
||||
{
|
||||
// the argument list is complete, now call the function
|
||||
template<typename Args>
|
||||
static inline
|
||||
InvokeResultCodes apply(Function func, InvokeArgs&, Args const &args)
|
||||
{
|
||||
boost::fusion::invoke(func,args);
|
||||
|
||||
return IRC_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct DoNothing
|
||||
{
|
||||
static void apply(SLNet::BitStream &bitStream, T& t)
|
||||
{
|
||||
(void) bitStream;
|
||||
(void) t;
|
||||
// printf("DoNothing\n");
|
||||
}
|
||||
};
|
||||
|
||||
struct WriteBitstream
|
||||
{
|
||||
static void applyArray(SLNet::BitStream &bitStream, SLNet::BitStream* t) {apply(bitStream,t);}
|
||||
static void apply(SLNet::BitStream &bitStream, SLNet::BitStream* t)
|
||||
{
|
||||
BitSize_t oldReadOffset = t->GetReadOffset();
|
||||
t->ResetReadPointer();
|
||||
bitStream.WriteCompressed(t->GetNumberOfBitsUsed());
|
||||
bitStream.Write(t);
|
||||
t->SetReadOffset(oldReadOffset);
|
||||
}
|
||||
};
|
||||
|
||||
//template <typename T>
|
||||
struct WritePtr
|
||||
{
|
||||
template <typename T2>
|
||||
static inline void applyArray(SLNet::BitStream &bitStream, T2 *t) {bitStream << (*t);}
|
||||
template <typename T2>
|
||||
static inline void apply(SLNet::BitStream &bitStream, T2 *t) {bitStream << (*t);}
|
||||
// template <>
|
||||
static inline void apply(SLNet::BitStream &bitStream, char *t) {bitStream << t;}
|
||||
// template <>
|
||||
static inline void apply(SLNet::BitStream &bitStream, unsigned char *t) {bitStream << t;}
|
||||
// template <>
|
||||
static inline void apply(SLNet::BitStream &bitStream, const char *t) {bitStream << t;}
|
||||
// template <>
|
||||
static inline void apply(SLNet::BitStream &bitStream, const unsigned char *t) {bitStream << t;}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct DoWrite
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_convertible<T*, SLNet::BitStream*>,
|
||||
WriteBitstream,
|
||||
WritePtr >::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct WriteWithNetworkIDPtr
|
||||
{
|
||||
static void apply(SLNet::BitStream &bitStream, T& t)
|
||||
{
|
||||
bool isNull;
|
||||
isNull=(t==0);
|
||||
bitStream.Write(isNull);
|
||||
if (isNull)
|
||||
return;
|
||||
RPC3Tag tag;
|
||||
__RPC3ClearPtr(t, &tag);
|
||||
bool deref = (tag.flag & RPC3_TAG_FLAG_DEREF) !=0;
|
||||
bool isArray = (tag.flag & RPC3_TAG_FLAG_ARRAY) !=0;
|
||||
bitStream.Write(deref);
|
||||
bitStream.Write(isArray);
|
||||
if (isArray)
|
||||
{
|
||||
bitStream.WriteCompressed(tag.count);
|
||||
}
|
||||
for (unsigned int i=0; i < tag.count; i++)
|
||||
{
|
||||
NetworkID inNetworkID=t->GetNetworkID();
|
||||
bitStream << inNetworkID;
|
||||
if (deref)
|
||||
{
|
||||
// skip bytes, write data, go back, write number of bits written, reset cursor
|
||||
bitStream.AlignWriteToByteBoundary();
|
||||
BitSize_t writeOffset1 = bitStream.GetWriteOffset();
|
||||
BitSize_t bitsUsed1=bitStream.GetNumberOfBitsUsed();
|
||||
bitStream.Write(bitsUsed1);
|
||||
bitsUsed1=bitStream.GetNumberOfBitsUsed();
|
||||
DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,t);
|
||||
BitSize_t writeOffset2 = bitStream.GetWriteOffset();
|
||||
BitSize_t bitsUsed2=bitStream.GetNumberOfBitsUsed();
|
||||
bitStream.SetWriteOffset(writeOffset1);
|
||||
bitStream.Write(bitsUsed2-bitsUsed1);
|
||||
bitStream.SetWriteOffset(writeOffset2);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct WriteWithoutNetworkIDNoPtr
|
||||
{
|
||||
static void apply(SLNet::BitStream &bitStream, T& t)
|
||||
{
|
||||
DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,&t);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct WriteWithoutNetworkIDPtr
|
||||
{
|
||||
static void apply(SLNet::BitStream &bitStream, T& t)
|
||||
{
|
||||
bool isNull;
|
||||
isNull=(t==0);
|
||||
bitStream.Write(isNull);
|
||||
if (isNull)
|
||||
return;
|
||||
|
||||
RPC3Tag tag;
|
||||
__RPC3ClearPtr((void*) t, &tag);
|
||||
bool isArray = (tag.flag & RPC3_TAG_FLAG_ARRAY) !=0;
|
||||
bitStream.Write(isArray);
|
||||
if (isArray)
|
||||
{
|
||||
bitStream.WriteCompressed(tag.count);
|
||||
}
|
||||
if (isArray)
|
||||
{
|
||||
for (unsigned int i=0; i < tag.count; i++)
|
||||
DoWrite< typename boost::remove_pointer<T>::type >::type::applyArray(bitStream,t+i);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,t);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SerializeCallParameterBranch
|
||||
{
|
||||
typedef typename boost::mpl::if_<
|
||||
typename IsRPC3Ptr<T>::type
|
||||
, DoNothing<T>
|
||||
, WriteWithoutNetworkIDPtr<T>
|
||||
>::type typeCheck1;
|
||||
|
||||
typedef typename boost::mpl::if_<
|
||||
boost::is_pointer<T>
|
||||
, typeCheck1
|
||||
, WriteWithoutNetworkIDNoPtr<T>
|
||||
>::type typeCheck2;
|
||||
|
||||
typedef typename boost::mpl::if_<
|
||||
typename ShouldReadNetworkID<T>::type
|
||||
, WriteWithNetworkIDPtr<T>
|
||||
, typeCheck2
|
||||
>::type type;
|
||||
};
|
||||
template<typename Function>
|
||||
struct GetBoundPointer_C
|
||||
{
|
||||
// typedef typename GetBoundPointer_C type;
|
||||
static FunctionPointer GetBoundPointer(Function f)
|
||||
{
|
||||
return FunctionPointer(false, boost::bind( & BoostRPCInvoker<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Function>
|
||||
struct GetBoundPointer_CPP
|
||||
{
|
||||
// typedef typename GetBoundPointer_CPP type;
|
||||
static FunctionPointer GetBoundPointer(Function f)
|
||||
{
|
||||
return FunctionPointer(true, boost::bind( & BoostRPCInvoker_ThisPtr<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ));
|
||||
}
|
||||
};
|
||||
template<typename Function>
|
||||
FunctionPointer GetBoundPointer(Function f)
|
||||
{
|
||||
return boost::mpl::if_<
|
||||
boost::is_member_function_pointer<Function>
|
||||
, GetBoundPointer_CPP<Function>
|
||||
, GetBoundPointer_C<Function>
|
||||
>::type::GetBoundPointer(f);
|
||||
|
||||
// return FunctionPointer(true, boost::bind( & BoostRPCInvoker<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user