137 lines
4.3 KiB
C++
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 |