haxis/Source/UnrealProject/External/TeaCallback.hpp

137 lines
4.3 KiB
C++

#ifndef _HEADER_TEA_CALLBACK
#define _HEADER_TEA_CALLBACK
#include <vector>
#include <type_traits>
namespace TeaLib
{
namespace Utility
{
#define NOVOIDFUNC(FuncRetVal) template<typename Test = ReturnValue> typename std::enable_if<!std::is_void<Test>::value, FuncRetVal>::type
template<typename ReturnValue, typename... Arguments>
class ReturnCallback
{
private:
// Typedef for comparing function pointers.
typedef ReturnValue(ReturnCallback::*CompareHandle)(Arguments...);
struct CallbackStructBase
{
public:
virtual ~CallbackStructBase() {};
virtual ReturnValue Call(Arguments...) = 0;
virtual bool Compare(ReturnValue(*a_CallbackFunction)(Arguments...))
{
return false;
};
virtual bool Compare(void* a_ClassInstance, CompareHandle a_CallbackFunction)
{
return false;
};
};
struct CallbackStruct : public CallbackStructBase
{
public:
virtual ReturnValue Call(Arguments... a_Arg)
{
return m_CallbackFunction(a_Arg...);
}
virtual bool Compare(ReturnValue(*a_CallbackFunction)(Arguments...))
{
return (a_CallbackFunction == m_CallbackFunction);
};
ReturnValue(*m_CallbackFunction)(Arguments...);
};
template<typename ClassType> struct ClassCallbackStruct : public CallbackStructBase
{
public:
virtual ReturnValue Call(Arguments... a_Arg)
{
return (m_ClassInstance->*m_CallbackFunction)(a_Arg...);
}
virtual bool Compare(void* a_ClassInstance, CompareHandle a_CallbackFunction)
{
CompareHandle compareHandle;
memcpy(&compareHandle, &m_CallbackFunction, sizeof(CompareHandle));
return ((a_ClassInstance == m_ClassInstance) && (a_CallbackFunction == compareHandle));
};
ClassType* m_ClassInstance;
ReturnValue(ClassType::*m_CallbackFunction)(Arguments...);
};
public:
virtual ~ReturnCallback()
{
for (int i = (int)m_CallbackFunctions.size() - 1; i >= 0; i--)
{
delete m_CallbackFunctions[i];
}
m_CallbackFunctions.clear();
}
void Call(Arguments... a_Arg)
{
for (auto it : m_CallbackFunctions)
{
it->Call(a_Arg...);
}
}
NOVOIDFUNC(void) Call(std::vector<ReturnValue>* a_ReturnValues, Arguments... a_Arg)
{
for (auto it : m_CallbackFunctions)
{
a_ReturnValues->push_back(it->Call(a_Arg...));
}
}
void Register(ReturnValue(*a_CallbackFunction)(Arguments...))
{
CallbackStruct* newCallback = new CallbackStruct();
newCallback->m_CallbackFunction = a_CallbackFunction;
m_CallbackFunctions.push_back(newCallback);
}
template<typename ClassType> void Register(ClassType* a_ClassInstance, ReturnValue(ClassType::*a_CallbackFunction)(Arguments...))
{
ClassCallbackStruct<ClassType>* newCallback = new ClassCallbackStruct<ClassType>();
newCallback->m_ClassInstance = a_ClassInstance;
newCallback->m_CallbackFunction = a_CallbackFunction;
m_CallbackFunctions.push_back(newCallback);
}
// Removes the first registered callback that matches the function.
void Deregister(ReturnValue(*a_CallbackFunction)(Arguments...))
{
for (unsigned int i = 0; i < m_CallbackFunctions.size(); i++)
{
if (m_CallbackFunctions[i]->Compare(a_CallbackFunction))
{
delete m_CallbackFunctions[i];
m_CallbackFunctions.erase(m_CallbackFunctions.begin() + i);
break;
}
}
}
// Removes the first registered callback that matches the class instance and the function.
template<typename ClassType> void Deregister(ClassType* a_ClassInstance, ReturnValue(ClassType::*a_CallbackFunction)(Arguments...))
{
CompareHandle compareHandle;
memcpy(&compareHandle, &a_CallbackFunction, sizeof(CompareHandle));
for (unsigned int i = 0; i < m_CallbackFunctions.size(); i++)
{
if (m_CallbackFunctions[i]->Compare(a_ClassInstance, compareHandle))
{
delete m_CallbackFunctions[i];
m_CallbackFunctions.erase(m_CallbackFunctions.begin() + i);
break;
}
}
}
private:
std::vector<CallbackStructBase*> m_CallbackFunctions;
};
// Alias template for callbacks that return void.
template<typename... Arguments>
using Callback = ReturnCallback<void, Arguments...>;
#undef NOVOIDFUNC
};
};
#endif