/** @file functor.h
 *  C++ BaseType Function Implementation 
 *	@author nbeatty@ea.com
 *
 *	EABaseTypes
 *	(c) 2011 Electronic Arts Inc. 
 */

#ifndef EABASETYPES_BASE_FUNCTOR_H
#define EABASETYPES_BASE_FUNCTOR_H

#include "eaassert/eaassert.h"

#include "EABaseTypes/datatypes.h"
#include "EABaseTypes/nativeencoder.h"
#include "EABaseTypes/nativetraits.h"

#if !defined(EA_FINAL)
#include "EABaseTypes/ptruserdata.h"
#endif

#include "EABaseTypes/profile.h"

#include "EASTLICA/hash_map.h"

namespace EA
{
	namespace Types
	{
		namespace Native
		{
			static const unsigned int CALLER_TYPE = 0x47486932;
		}

		/*!
		*	Template function for adding an optimized caller for Functors
		*	@tparam Decoder	The argument decoder type for the caller
		*	@tparam	Encoder The result encoder type for the caller
		*	@param	id		The unique id for the caller
		*/
		template<template<class> class Decoder, class Encoder>
		void AddNativeCaller(CallerMap* callerMap, unsigned int id)
		{
			callerMap->Add(Native::CALLER_TYPE, id, Decoder<NativeEncoder>::Decode, NativeDecoder<Encoder>::Decode);
		}

		/*! @class FunctorBase functor.h	"EABaseTypes/functor.h"
		*	@brief Base class for Functors, should only be created by derived classes
		*/
		class FunctorBase : public Function
		{
		public:
		
			/*!
			*	Get a clone of this instance
			*	@return BaseTypeReturn	pointer to the new instnace
			*	@attention we aren't creating a new instance here, simply addref the current one and return a pointer to it
			*/
			virtual BaseTypeReturn Clone();

			/*!
			*	Compare two functions
			*	@param[in] FunctionIn	Function to compare to
			*	@return bool True iff the functions are equal, false otherwise
			*/
			virtual bool Equals(FunctionIn pCompare);
	
			/*!
			*	Compare two functions
			*	@return unsigned int The id defined to this type of Function class
			*/
			virtual EA::Type::TypeID GetFunctionType() = 0;

			bool operator==(const FunctorBase &rhs) const;

			using Function::Call;

		protected:
		
			/*!
			*	FunctorBase C'tor for C style function
			*	@param[in]	pFunction pointer to function call
			*	@attention Only derived class can call this constructor
			*/	
			FunctorBase(Factory* factory, void* pFunction);

			/*!
			*	FunctorBase C'tor for Member functions
			*	@param[in]	executePtr pointer to the execute function
			*	@param[in]	object object instance for this function
			*	@param[in]	memFunc Member function instance
			*	@param[in]	memFuncSize Size of member function
			*	@attention Only derived class can call this constructor
			*/	
			FunctorBase(Factory* factory, void * executePtr, void *object, void *memFunc, size_t memFuncSize);

			virtual ~FunctorBase();

			/*!
			*	Get the execute function pointer
			*	@return void* Pointer to the execute function, NULL if this is a C style Functor
			*/	
			inline void *GetExecuteFunc() const {return mExecuteFunc;}
		
			/*!
			*	Get the C style function pointer
			*	@return void*	Pointer to the C style function, NULL if this is a Member function Functor
			*/	
			inline void *GetFunction() const {return mFunc;}

			/*!
			*	Get the Member function
			*	@return	const char* Pointer to the Member function, NULL if this is a C style Functor
			*/	
			inline const char *GetMemberFunction() const {return mMemberFunc;}

			/*!
			*	Get the Object instance
			*	@return	 void* Pointer to the object instance, NULL if this is a C style Functor
			*/	
			inline void *GetObject() const {return mObject;}

			template<typename T>
			inline void SetObject(T* object)
			{
				mObject = object;
#if !defined(EA_FINAL)
				(*mDebugInfo->AsArray())[1] = PtrUserData<T>::Create(mFactory, object);
#endif
			}
		
			/*!
			*	Clear the contents of this Functor
			*/
			void clear();
		
		private:

			void *mExecuteFunc;
			void *mObject;
			union
			{
				void *mFunc;
				char mMemberFunc[16];
			};
		};

		/*! @class FunctorRaw functor.h	"EABaseTypes/functor.h"
		*	@brief Raw FunctorBase implementation
		*/
		class FunctorRaw : public FunctorBase
		{
		public:	
			/*! The C function type for this functor */
			typedef BaseTypeReturn (*FuncCallback)(ArrayIn);
		
			/*!
			*	FunctorRaw C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a function that takes a ArrayIn
			*/	
			FunctorRaw(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void*) function)
			{
			}

			/*!
			*	FunctorRaw C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(ArrayIn) Member function to call
			*/	
			template <class T>
			FunctorRaw(Factory* factory, T* obj, BaseTypeReturn (T::*func)(ArrayIn))
				: FunctorBase(factory,
							  (void *)(ExecuteFunc) (FunctorRaw::template ExecuteFunction<T, BaseTypeReturn (T::*)(ArrayIn)>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Call the function
			*	@param[in] ArrayIn		Array of BaseTypes containing the paramters to be passed to the function
			*	@return	BaseTypeReturn	The return value
			*/
			virtual Types::BaseTypeReturn Call(ArrayIn pParams)
			{
				CheckData(pParams);
				return (*this)(pParams);
			}

			using FunctorBase::Call;

			/*! Executes the functor */
			Types::BaseTypeReturn operator()(ArrayIn pParams) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, pParams);
				else // regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())(pParams);
				}
			}

			EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

		private:
			typedef BaseTypeReturn (*ExecuteFunc)(const FunctorRaw*, ArrayIn);

			template <class T, class MemFunc>
			static BaseTypeReturn ExecuteFunction(const FunctorRaw* base, ArrayIn pParams)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(base->GetMemberFunction()));
				return (object->*memFunc)(pParams);
			}
		};

		//lint -esym(119, EA::Types::Functor<*>::Functor)
		/*! @class Functor functor.h	"EABaseTypes/functor.h"
		*	@brief 0 parameter FunctorBase implementation 
		*	@tparam	R the return type
		*/
		template<typename R>
		class Functor : public FunctorBase
		{
		public:	
			/*! The C function type for this functor */
			typedef R (*FuncCallback)();

			/*!
			*	Functor	C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 0 paramter function
			*/	
			Functor(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor	C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)() Member function to call
			*/	
			template <class T>
			Functor(Factory* factory, T* obj, R (T::*func)())
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) (Functor::template ExecuteFunction<T, R (T::*)()>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor	C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)() Member function to call
			*/	
			template <class T>
			Functor(Factory* factory, T* obj, R (T::*func)() const)
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) (Functor::template ExecuteFunction<T, R (T::*)() const>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[1] =
					{
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);
				
				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)();
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()() const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this);
				else  // regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())();
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor *);

			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor *base)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(base->GetMemberFunction()));
				return (object->*memFunc)();
			}
		};

		/*! @class Functor functor.h	"EABaseTypes/functor.h"
		*	@brief 0 parameter FunctorBase implementation, specialized for a void return type
		*/
		template<>
		class Functor<void> : public FunctorBase
		{
		public:	
			/*! The C function type for this functor */
			typedef void (*FuncCallback)();

			/*!
			*	Functor	C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 0 paramter function
			*/	
			Functor(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor	C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)() Member function to call
			*/	
			template <class T>
			Functor(Factory* factory, T* obj, void (T::*func)())
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) (Functor::template ExecuteFunction<T, void (T::*)()>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor	C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)() Member function to call
			*/	
			template <class T>
			Functor(Factory* factory, T* obj, void (T::*func)() const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) (Functor::template ExecuteFunction<T, void (T::*)() const>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor_Decode");

				CheckData(decoderParams, defaultDecode);
				
				(*this)();

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()() const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this);
				else  // regular function
				{
					EA_ASSERT(GetFunction() != 0);
					(*(FuncCallback) GetFunction())();
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor *);

			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor *base)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(base->GetMemberFunction()));
				(object->*memFunc)();
			}
		};

		//lint -esym(119, EA::Types::Functor1<*>::Functor1)
		/*! @class Functor1 functor.h	"EABaseTypes/functor.h"
		*	@brief 1 parameter FunctorBase implementation 
		*	@tparam	R the return type
		*	@tparam	P1 the type of paramter 1
		*/
		template <typename R, typename P1>
		class Functor1 : public FunctorBase
		{
		public:	
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1);
		
			/*!
			*	Functor1 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 1 parameter function
			*/	
			Functor1(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor1 C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1) Member function to call
			*/	
			template <class T>
			Functor1(Factory* factory, T* obj, R (T::*func)(P1))
				: FunctorBase(factory,
							  (void *)(ExecuteFunc) (Functor1<R, P1>::template ExecuteFunction<T, R (T::*)(P1)>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor1 C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1) Member function to call
			*/	
			template <class T>
			Functor1(Factory* factory, T* obj, R (T::*func)(P1) const)
				: FunctorBase(factory,
							  (void *)(ExecuteFunc) (Functor1<R, P1>::template ExecuteFunction<T, R (T::*)(P1) const>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor1_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[2] =
					{
						&argument1Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0); 
					return (*(FuncCallback) GetFunction())(arg1);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor1<R, P1> *, P1);

			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor1<R, P1> *base, P1 arg1)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1);
			}
		};

		/*! @class Functor1 functor.h	"EABaseTypes/functor.h"
		*	@brief 1 parameter FunctorBase implementation, specialized for a void return type
		*	@tparam	P1 the type of paramter 1
		*/
		template <typename P1>
		class Functor1<void, P1> : public FunctorBase
		{
		public:	
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1);
		
			/*!
			*	Functor1 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 1 parameter function
			*/	
			Functor1(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor1 C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1) Member function to call
			*/	
			template <class T>
			Functor1(Factory* factory, T* obj, void (T::*func)(P1))
				: FunctorBase(factory,
							  (void *)(ExecuteFunc) (Functor1<void, P1>::template ExecuteFunction<T, void (T::*)(P1)>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor1 C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1) Member function to call
			*/	
			template <class T>
			Functor1(Factory* factory, T* obj, void (T::*func)(P1) const)
				: FunctorBase(factory,
							  (void *)(ExecuteFunc) (Functor1<void, P1>::template ExecuteFunction<T, void (T::*)(P1) const>),
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor1_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[2] =
					{
						&argument1Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1));

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0); 
					(*(FuncCallback) GetFunction())(arg1);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor1<void, P1> *, P1);

			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor1<void, P1> *base, P1 arg1)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(base->GetMemberFunction()));
				(object->*memFunc)(arg1);
			}
		};

		//lint -esym(119, EA::Types::Functor2<*>::Functor2)
		/*! @class Functor2 functor.h	"EABaseTypes/functor.h"
		*	@brief 2 parameter FunctorBase implementation
		*	@tparam	R the return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*/
		template <typename R, typename P1, typename P2>
		class Functor2 : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1, P2);
		
			/*!
			*	Functor2 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 2 parameter function
			*/	
			Functor2(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor2 C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2) Member function to call
			*/	
			template <class T>
			Functor2(Factory* factory, T* obj, R (T::*func)(P1, P2))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor2<R, P1, P2>::template ExecuteFunction<T, R (T::*)(P1, P2)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor2 C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2) Member function to call
			*/	
			template <class T>
			Functor2(Factory* factory, T* obj, R (T::*func)(P1, P2) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor2<R, P1, P2>::template ExecuteFunction<T, R (T::*)(P1, P2) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor2_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[3] =
					{
						&argument1Context,
						&argument2Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1, P2 arg2) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2);
				else //regular function
				{
					EA_ASSERT((GetFunction() != 0));
					return (*(FuncCallback) GetFunction())(arg1, arg2);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor2<R, P1, P2> *, P1, P2);
			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor2<R, P1, P2> *base, P1 arg1, P2 arg2)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1, arg2);
			}
		};

		/*! @class Functor2 functor.h	"EABaseTypes/functor.h"
		*	@brief 2 parameter FunctorBase implementation, specialized for a void return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*/
		template <typename P1, typename P2>
		class Functor2<void, P1, P2> : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1, P2);
		
			/*!
			*	Functor2 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 2 parameter function
			*/	
			Functor2(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor2 C'tor for Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2) Member function to call
			*/	
			template <class T>
			Functor2(Factory* factory, T* obj, void (T::*func)(P1, P2))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor2<void, P1, P2>::template ExecuteFunction<T, void (T::*)(P1, P2)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor2 C'tor for const Member functions
			*	@tparam	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2) Member function to call
			*/	
			template <class T>
			Functor2(Factory* factory, T* obj, void (T::*func)(P1, P2) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor2<void, P1, P2>::template ExecuteFunction<T, void (T::*)(P1, P2) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor2_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[3] =
					{
						&argument1Context,
						&argument2Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2));

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1, P2 arg2) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2);
				else //regular function
				{
					EA_ASSERT((GetFunction() != 0));
					(*(FuncCallback) GetFunction())(arg1, arg2);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor2<void, P1, P2> *, P1, P2);
			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor2<void, P1, P2> *base, P1 arg1, P2 arg2)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				(object->*memFunc)(arg1, arg2);
			}
		};

		//lint -esym(119, EA::Types::Functor3<*>::Functor3)
		/*! @class Functor3 functor.h	"EABaseTypes/functor.h"
		*	@brief 3 parameter FunctorBase implementation
		*	@tparam	R the return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*/
		template <typename R, typename P1, typename P2, typename P3>
		class Functor3 : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1, P2, P3);
		
			/*!
			*	Functor3 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 3 parameter function
			*/	
			Functor3(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor3 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3) Member function to call
			*/	
			template <class T>
			Functor3(Factory* factory, T* obj, R (T::*func)(P1, P2, P3))
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor3<R, P1, P2, P3>::template ExecuteFunction<T, R (T::*)(P1, P2, P3)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor3 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3) Member function to call
			*/	
			template <class T>
			Functor3(Factory* factory, T* obj, R (T::*func)(P1, P2, P3) const)
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor3<R, P1, P2, P3>::template ExecuteFunction<T, R (T::*)(P1, P2, P3) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor3_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[4] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1, P2 arg2, P3 arg3) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())(arg1, arg2, arg3);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor3<R, P1, P2, P3> *, P1, P2, P3);
			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor3<R, P1, P2, P3> *base, P1 arg1, P2 arg2, P3 arg3)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1, arg2, arg3);
			}
		};

		/*! @class Functor3 functor.h	"EABaseTypes/functor.h"
		*	@brief 3 parameter FunctorBase implementation, specialized for a void return value
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*/
		template <typename P1, typename P2, typename P3>
		class Functor3<void, P1, P2, P3> : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1, P2, P3);
		
			/*!
			*	Functor3 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 3 parameter function
			*/	
			Functor3(Factory* factory, FuncCallback function)
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor3 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3) Member function to call
			*/	
			template <class T>
			Functor3(Factory* factory, T* obj, void (T::*func)(P1, P2, P3))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor3<void, P1, P2, P3>::template ExecuteFunction<T, void (T::*)(P1, P2, P3)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor3 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3) Member function to call
			*/	
			template <class T>
			Functor3(Factory* factory, T* obj, void (T::*func)(P1, P2, P3) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor3<void, P1, P2, P3>::template ExecuteFunction<T, void (T::*)(P1, P2, P3) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor3_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[4] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3));

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1, P2 arg2, P3 arg3) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					(*(FuncCallback) GetFunction())(arg1, arg2, arg3);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor3<void, P1, P2, P3> *, P1, P2, P3);
			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor3<void, P1, P2, P3> *base, P1 arg1, P2 arg2, P3 arg3)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				(object->*memFunc)(arg1, arg2, arg3);
			}
		};

		//lint -esym(119, EA::Types::Functor4<*>::Functor4)
		/*! @class Functor4 functor.h	"EABaseTypes/functor.h"
		*	@brief 4 parameter FunctorBase implementation
		*	@tparam	R the return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*/
		template <typename R, typename P1, typename P2, typename P3, typename P4>
		class Functor4 : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1, P2, P3, P4);

			/*!
			*	Functor4 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 4 parameter function
			*/	
			Functor4(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor4 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4) Member function to call
			*/
			template <class T>
			Functor4(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4))
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor4<R, P1, P2, P3, P4>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor4 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4) Member function to call
			*/
			template <class T>
			Functor4(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4) const)
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor4<R, P1, P2, P3, P4>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor4_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[5] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}
		
			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor4<R, P1, P2, P3, P4> *, P1, P2, P3, P4);
			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor4<R, P1, P2, P3, P4> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1, arg2, arg3, arg4);
			}
		};

		/*! @class Functor4 functor.h	"EABaseTypes/functor.h"
		*	@brief 4 parameter FunctorBase implementation, specialized for a void return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*/
		template <typename P1, typename P2, typename P3, typename P4>
		class Functor4<void, P1, P2, P3, P4> : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1, P2, P3, P4);

			/*!
			*	Functor4 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 4 parameter function
			*/	
			Functor4(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor4 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4) Member function to call
			*/
			template <class T>
			Functor4(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4))
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor4<void, P1, P2, P3, P4>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor4 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4) Member function to call
			*/
			template <class T>
			Functor4(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4) const)
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor4<void, P1, P2, P3, P4>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor4_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[5] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4));
				
				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					(*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor4<void, P1, P2, P3, P4> *, P1, P2, P3, P4);
			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor4<void, P1, P2, P3, P4> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				(object->*memFunc)(arg1, arg2, arg3, arg4);
			}
		};

		//lint -esym(119, EA::Types::Functor5<*>::Functor5)
		/*! @class Functor5 functor.h	"EABaseTypes/functor.h"
		*	@brief 5 parameter FunctorBase implementation
		*	@tparam	R the return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*	@tparam P5 type of parameter 5
		*/
		template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
		class Functor5 : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1, P2, P3, P4, P5);
		
			/*!
			*	Functor5 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 5 parameter function
			*/	
			Functor5(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor5 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4, P5) Member function to call
			*/
			template <class T>
			Functor5(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4, P5))
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor5<R, P1, P2, P3, P4, P5>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4, P5)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor5 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4, P5) Member function to call
			*/
			template <class T>
			Functor5(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4, P5) const)
				: FunctorBase(factory, 
							  (void *) (ExecuteFunc) Functor5<R, P1, P2, P3, P4, P5>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4, P5) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor5_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;
				typedef NativeTraits<P5> P5Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				typename P5Traits::EncodeValue argument5(mFactory);
				typename P5Traits::EncoderContext argument5Context(mFactory, NULL, P5Traits::GetEncodePointer(argument5));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[6] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&argument5Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4), P5Traits::GetValue(argument5));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4, arg5);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4, arg5);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor5<R, P1, P2, P3, P4, P5> *, P1, P2, P3, P4, P5);
			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor5<R, P1, P2, P3, P4, P5> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1, arg2, arg3, arg4, arg5);
			}
		};

		/*! @class Functor5 functor.h	"EABaseTypes/functor.h"
		*	@brief 5 parameter FunctorBase implementation, specialized for a void return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*	@tparam P5 type of parameter 5
		*/
		template <typename P1, typename P2, typename P3, typename P4, typename P5>
		class Functor5<void, P1, P2, P3, P4, P5> : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1, P2, P3, P4, P5);
		
			/*!
			*	Functor5 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 5 parameter function
			*/	
			Functor5(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor5 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4, P5) Member function to call
			*/
			template <class T>
			Functor5(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4, P5))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor5<void, P1, P2, P3, P4, P5>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4, P5)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor5 C'tor for const Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4, P5) Member function to call
			*/
			template <class T>
			Functor5(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4, P5) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor5<void, P1, P2, P3, P4, P5>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4, P5) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor5_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;
				typedef NativeTraits<P5> P5Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				typename P5Traits::EncodeValue argument5(mFactory);
				typename P5Traits::EncoderContext argument5Context(mFactory, NULL, P5Traits::GetEncodePointer(argument5));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[6] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&argument5Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4), P5Traits::GetValue(argument5));

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4, arg5);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					(*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4, arg5);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor5<void, P1, P2, P3, P4, P5> *, P1, P2, P3, P4, P5);
			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor5<void, P1, P2, P3, P4, P5> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				(object->*memFunc)(arg1, arg2, arg3, arg4, arg5);
			}
		};

		//lint -esym(119, EA::Types::Functor6<*>::Functor6)
		/*! @class Functor6 functor.h	"EABaseTypes/functor.h"
		*	@brief 6 parameter FunctorBase implementation
		*	@tparam	R the return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*	@tparam P5 type of parameter 5
		*	@tparam P6 type of parameter 6
		*/
		template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		class Functor6 : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef R (*FuncCallback)(P1, P2, P3, P4, P5, P6);
		
			/*!
			*	Functor5 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 6 parameter function
			*/	
			Functor6(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor6 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4, P5, P6) Member function to call
			*/
			template <class T>
			Functor6(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4, P5, P6))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor6<R, P1, P2, P3, P4, P5, P6>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4, P5, P6)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor6 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	R (T::*func)(P1, P2, P3, P4, P5, P6) Member function to call
			*/
			template <class T>
			Functor6(Factory* factory, T* obj, R (T::*func)(P1, P2, P3, P4, P5, P6) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor6<R, P1, P2, P3, P4, P5, P6>::template ExecuteFunction<T, R (T::*)(P1, P2, P3, P4, P5, P6) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor6_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;
				typedef NativeTraits<P5> P5Traits;
				typedef NativeTraits<P6> P6Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				typename P5Traits::EncodeValue argument5(mFactory);
				typename P5Traits::EncoderContext argument5Context(mFactory, NULL, P5Traits::GetEncodePointer(argument5));
				typename P6Traits::EncodeValue argument6(mFactory);
				typename P6Traits::EncoderContext argument6Context(mFactory, NULL, P6Traits::GetEncodePointer(argument6));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[7] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&argument5Context,
						&argument6Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);
			
				typedef NativeTraits<R> RTraits;
			
				typename RTraits::DecodeValue result(mFactory);
				NativeDecoderArgument decoderArguments[1] = { { RTraits::GetDecoderType(), RTraits::GetDecodePointer(result), RTraits::GetDecodeFunction() } };
				NativeDecoderParams resultDecoderParams(mFactory, decoderArguments, 1);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				result = (*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4), P5Traits::GetValue(argument5), P6Traits::GetValue(argument6));
				
				if(decode != NULL)
				{
					decode->second(encoder, &resultDecoderParams);
				}
				else
				{
					NativeDecoder<IEncoder>::Decode(defaultEncoder, &resultDecoderParams);
				}

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			R operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6) const
			{
				if (GetExecuteFunc() != 0) //member function
					return (*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4, arg5, arg6);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					return (*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4, arg5, arg6);
				}
			}

		private:

			typedef R (*ExecuteFunc)(const Functor6<R, P1, P2, P3, P4, P5, P6> *, P1, P2, P3, P4, P5, P6);
			template <class T, class MemFunc>
			static R ExecuteFunction(const Functor6<R, P1, P2, P3, P4, P5, P6> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				return (object->*memFunc)(arg1, arg2, arg3, arg4, arg5, arg6);
			}
		};

		/*! @class Functor6 functor.h	"EABaseTypes/functor.h"
		*	@brief 6 parameter FunctorBase implementation, specialized for a void return type
		*	@tparam P1 type of parameter 1
		*	@tparam P2 type of parameter 2
		*	@tparam P3 type of parameter 3
		*	@tparam P4 type of parameter 4
		*	@tparam P5 type of parameter 5
		*	@tparam P6 type of parameter 6
		*/
		template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		class Functor6<void, P1, P2, P3, P4, P5, P6> : public FunctorBase
		{
		public:
			/*! The C function type for this functor */
			typedef void (*FuncCallback)(P1, P2, P3, P4, P5, P6);
		
			/*!
			*	Functor5 C'tor for C style functions
			*	@param[in]	FuncCallback pointer to a 6 parameter function
			*/	
			Functor6(Factory* factory, FuncCallback function) 
				: FunctorBase(factory, (void *) function)
			{
			}

			/*!
			*	Functor6 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4, P5, P6) Member function to call
			*/
			template <class T>
			Functor6(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4, P5, P6))
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor6<void, P1, P2, P3, P4, P5, P6>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4, P5, P6)>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			/*!
			*	Functor6 C'tor for Member functions
			*	@tparam T	The class type of this function
			*	@param[in]	obj instance of the class
			*	@param[in]	void (T::*func)(P1, P2, P3, P4, P5, P6) Member function to call
			*/
			template <class T>
			Functor6(Factory* factory, T* obj, void (T::*func)(P1, P2, P3, P4, P5, P6) const)
				: FunctorBase(factory,
							  (void *) (ExecuteFunc) Functor6<void, P1, P2, P3, P4, P5, P6>::template ExecuteFunction<T, void (T::*)(P1, P2, P3, P4, P5, P6) const>,
							  (void *) obj,
							  &func,
							  sizeof(func))
			{
#if !defined(EA_FINAL)
				mDebugInfo->AsArray()->push_back(PtrUserData<T>::Create(factory, obj));
#endif
			}

			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  DecodeFunction defaultDecode,
							  IEncoder* defaultEncoder)
			{
				EABASETYPES_PROFILE_BEGIN(0, "Functor6_Decode");

				CheckData(decoderParams, defaultDecode);

				const eastl::pair<DecodeFunction, DecodeFunction>* decode = mFactory->GetCallerMap()->Get(Native::CALLER_TYPE, id);

				typedef NativeTraits<P1> P1Traits;
				typedef NativeTraits<P2> P2Traits;
				typedef NativeTraits<P3> P3Traits;
				typedef NativeTraits<P4> P4Traits;
				typedef NativeTraits<P5> P5Traits;
				typedef NativeTraits<P6> P6Traits;

				typename P1Traits::EncodeValue argument1(mFactory);
				typename P1Traits::EncoderContext argument1Context(mFactory, NULL, P1Traits::GetEncodePointer(argument1));
				typename P2Traits::EncodeValue argument2(mFactory);
				typename P2Traits::EncoderContext argument2Context(mFactory, NULL, P2Traits::GetEncodePointer(argument2));
				typename P3Traits::EncodeValue argument3(mFactory);
				typename P3Traits::EncoderContext argument3Context(mFactory, NULL, P3Traits::GetEncodePointer(argument3));
				typename P4Traits::EncodeValue argument4(mFactory);
				typename P4Traits::EncoderContext argument4Context(mFactory, NULL, P4Traits::GetEncodePointer(argument4));
				typename P5Traits::EncodeValue argument5(mFactory);
				typename P5Traits::EncoderContext argument5Context(mFactory, NULL, P5Traits::GetEncodePointer(argument5));
				typename P6Traits::EncodeValue argument6(mFactory);
				typename P6Traits::EncoderContext argument6Context(mFactory, NULL, P6Traits::GetEncodePointer(argument6));
				EndContext endContext;

				NativeEncoder::Argument argumentEncoderParams[7] =
					{
						&argument1Context,
						&argument2Context,
						&argument3Context,
						&argument4Context,
						&argument5Context,
						&argument6Context,
						&endContext
					};
					
				NativeEncoder argumentEncoder(argumentEncoderParams);

				if(decode != NULL)
				{
					decode->first(&argumentEncoder, decoderParams);
				}
				else
				{
					IEncoderImpl<NativeEncoder> defaultArgumentEncoder(&argumentEncoder);
					defaultDecode(&defaultArgumentEncoder, decoderParams);
				}
				
				(*this)(P1Traits::GetValue(argument1), P2Traits::GetValue(argument2), P3Traits::GetValue(argument3), P4Traits::GetValue(argument4), P5Traits::GetValue(argument5), P6Traits::GetValue(argument6));

				EABASETYPES_PROFILE_END();
			}

			using FunctorBase::Call;

			virtual EA::Type::TypeID GetFunctionType()
			{
				return EA::Type::TypeOf(*this);
			}

			/*! Executes the functor */
			void operator()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6) const
			{
				if (GetExecuteFunc() != 0) //member function
					(*(ExecuteFunc) GetExecuteFunc())(this, arg1, arg2, arg3, arg4, arg5, arg6);
				else //regular function
				{
					EA_ASSERT(GetFunction() != 0);
					(*(FuncCallback) GetFunction())(arg1, arg2, arg3, arg4, arg5, arg6);
				}
			}

		private:

			typedef void (*ExecuteFunc)(const Functor6<void, P1, P2, P3, P4, P5, P6> *, P1, P2, P3, P4, P5, P6);
			template <class T, class MemFunc>
			static void ExecuteFunction(const Functor6<void, P1, P2, P3, P4, P5, P6> *base, P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
			{
				T *object = (T *) base->GetObject();
				MemFunc &memFunc(*(MemFunc*)(void *)(base->GetMemberFunction()));
				(object->*memFunc)(arg1, arg2, arg3, arg4, arg5, arg6);
			}
		};

		template<typename R>
		struct BaseTypeTraits1<R (*)()>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)()) { return new (factory) Functor<R>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)()) { return new (factory) Functor<R>(factory, f); }
		};

		template<typename T, typename R>
		struct BaseTypeTraits2<T*, R (T::*)()>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)()) { return new (factory) Functor<R>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)()) { return new (factory) Functor<R>(factory, t, f); }
		};

		template<typename R, typename P1>
		struct BaseTypeTraits1<R (*)(P1)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1)) { return new (factory) Functor1<R, P1>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1)) { return new (factory) Functor1<R, P1>(factory, f); }
		};

		template<typename T, typename R, typename P1>
		struct BaseTypeTraits2<T*, R (T::*)(P1)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1)) { return new (factory) Functor1<R, P1>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1)) { return new (factory) Functor1<R, P1>(factory, t, f); }
		};

		template<typename R, typename P1, typename P2>
		struct BaseTypeTraits1<R (*)(P1, P2)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1, P2)) { return new (factory) Functor2<R, P1, P2>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1, P2)) { return new (factory) Functor2<R, P1, P2>(factory, f); }
		};

		template<typename T, typename R, typename P1, typename P2>
		struct BaseTypeTraits2<T*, R (T::*)(P1, P2)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1, P2)) { return new (factory) Functor2<R, P1, P2>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1, P2)) { return new (factory) Functor2<R, P1, P2>(factory, t, f); }
		};

		template<typename R, typename P1, typename P2, typename P3>
		struct BaseTypeTraits1<R (*)(P1, P2, P3)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1, P2, P3)) { return new (factory) Functor3<R, P1, P2, P3>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1, P2, P3)) { return new (factory) Functor3<R, P1, P2, P3>(factory, f); }
		};

		template<typename T, typename R, typename P1, typename P2, typename P3>
		struct BaseTypeTraits2<T*, R (T::*)(P1, P2, P3)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1, P2, P3)) { return new (factory) Functor3<R, P1, P2, P3>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1, P2, P3)) { return new (factory) Functor3<R, P1, P2, P3>(factory, t, f); }
		};

		template<typename R, typename P1, typename P2, typename P3, typename P4>
		struct BaseTypeTraits1<R (*)(P1, P2, P3, P4)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1, P2, P3, P4)) { return new (factory) Functor4<R, P1, P2, P3, P4>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1, P2, P3, P4)) { return new (factory) Functor4<R, P1, P2, P3, P4>(factory, f); }
		};

		template<typename T, typename R, typename P1, typename P2, typename P3, typename P4>
		struct BaseTypeTraits2<T*, R (T::*)(P1, P2, P3, P4)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4)) { return new (factory) Functor4<R, P1, P2, P3, P4>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4)) { return new (factory) Functor4<R, P1, P2, P3, P4>(factory, t, f); }
		};

		template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
		struct BaseTypeTraits1<R (*)(P1, P2, P3, P4, P5)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1, P2, P3, P4, P5)) { return new (factory) Functor5<R, P1, P2, P3, P4, P5>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1, P2, P3, P4, P5)) { return new (factory) Functor5<R, P1, P2, P3, P4, P5>(factory, f); }
		};

		template<typename T, typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
		struct BaseTypeTraits2<T*, R (T::*)(P1, P2, P3, P4, P5)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4, P5)) { return new (factory) Functor5<R, P1, P2, P3, P4, P5>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4, P5)) { return new (factory) Functor5<R, P1, P2, P3, P4, P5>(factory, t, f); }
		};

		template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		struct BaseTypeTraits1<R (*)(P1, P2, P3, P4, P5, P6)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, R (*f)(P1, P2, P3, P4, P5, P6)) { return new (factory) Functor6<R, P1, P2, P3, P4, P5, P6>(factory, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, R (*f)(P1, P2, P3, P4, P5, P6)) { return new (factory) Functor6<R, P1, P2, P3, P4, P5, P6>(factory, f); }
		};

		template<typename T, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		struct BaseTypeTraits2<T*, R (T::*)(P1, P2, P3, P4, P5, P6)>
		{
			static EA::Types::BaseTypeReturn BaseType(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4, P5, P6)) { return new (factory) Functor6<R, P1, P2, P3, P4, P5, P6>(factory, t, f); }

			static EA::Types::FunctionReturn Function(Factory* factory, T* t, R (T::*f)(P1, P2, P3, P4, P5, P6)) { return new (factory) Functor6<R, P1, P2, P3, P4, P5, P6>(factory, t, f); }
		};
	}
}

#define EABASETYPES_FUNCTORS(EABASETYPES_GET_FACTORY)\
	class FunctorRaw : public EA::Types::FunctorRaw\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		FunctorRaw(EA::Types::FunctorRaw::FuncCallback function):EA::Types::FunctorRaw(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		FunctorRaw(T* obj, EA::Types::BaseTypeReturn (T::*func)(EA::Types::ArrayIn)):EA::Types::FunctorRaw(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R>\
	class Functor : public EA::Types::Functor<R>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor(typename Functor<R>::FuncCallback function):EA::Types::Functor<R>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor(T* obj, R (T::*func)()):EA::Types::Functor<R>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1>\
	class Functor1 : public EA::Types::Functor1<R, P1>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor1(typename EA::Types::Functor1<R, P1>::FuncCallback function):EA::Types::Functor1<R, P1>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor1(T* obj, R (T::*func)(P1)):EA::Types::Functor1<R, P1>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1, typename P2>\
	class Functor2 : public EA::Types::Functor2<R, P1, P2>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor2(typename EA::Types::Functor2<R, P1, P2>::FuncCallback function):EA::Types::Functor2<R, P1, P2>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor2(T* obj, R (T::*func)(P1, P2)):EA::Types::Functor2<R, P1, P2>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1, typename P2, typename P3>\
	class Functor3 : public EA::Types::Functor3<R, P1, P2, P3>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor3(typename EA::Types::Functor3<R, P1, P2, P3>::FuncCallback function):EA::Types::Functor3<R, P1, P2, P3>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor3(T* obj, R (T::*func)(P1, P2, P3)):EA::Types::Functor3<R, P1, P2, P3>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1, typename P2, typename P3, typename P4>\
	class Functor4 : public EA::Types::Functor4<R, P1, P2, P3, P4>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor4(typename EA::Types::Functor4<R, P1, P2, P3, P4>::FuncCallback function):EA::Types::Functor4<R, P1, P2, P3, P4>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor4(T* obj, R (T::*func)(P1, P2, P3, P4)):EA::Types::Functor4<R, P1, P2, P3, P4>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>\
	class Functor5 : public EA::Types::Functor5<R, P1, P2, P3, P4, P5>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor5(typename EA::Types::Functor5<R, P1, P2, P3, P4, P5>::FuncCallback function):EA::Types::Functor5<R, P1, P2, P3, P4, P5>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor5(T* obj, R (T::*func)(P1, P2, P3, P4, P5)):EA::Types::Functor5<R, P1, P2, P3, P4, P5>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};\
	\
	template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>\
	class Functor6 : public EA::Types::Functor6<R, P1, P2, P3, P4, P5, P6>\
	{\
	public:\
		EABASETYPES_NEW_OPERATORS(EABASETYPES_GET_FACTORY)\
		Functor6(typename EA::Types::Functor6<R, P1, P2, P3, P4, P5, P6>::FuncCallback function):EA::Types::Functor6<R, P1, P2, P3, P4, P5, P6>(EABASETYPES_GET_FACTORY, function) {}\
		template <class T>\
		Functor6(T* obj, R (T::*func)(P1, P2, P3, P4, P5, P6)):EA::Types::Functor6<R, P1, P2, P3, P4, P5, P6>(EABASETYPES_GET_FACTORY, obj, func) {}\
	};

#endif // EABASETYPES_BASE_FUNCTOR_H
