mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-02-20 13:54:14 +01:00
Untested reentrancy support; TODO: Test sh_stack and reentrancy extensively!
--HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40129
This commit is contained in:
parent
03ba0a371e
commit
17aa1b4c3f
@ -20,10 +20,10 @@
|
||||
// 1 - Initial revision
|
||||
// 2 - Changed to virtual functions for iterators and all queries
|
||||
// 3 - Added "hook loop status variable"
|
||||
// Future: Thread safe interface?
|
||||
// 4 - Reentrant
|
||||
|
||||
#define SH_IFACE_VERSION 3
|
||||
#define SH_IMPL_VERSION 2
|
||||
#define SH_IFACE_VERSION 4
|
||||
#define SH_IMPL_VERSION 3
|
||||
|
||||
#ifndef SH_GLOB_SHPTR
|
||||
#define SH_GLOB_SHPTR g_SHPtr
|
||||
@ -273,15 +273,6 @@ namespace SourceHook
|
||||
|
||||
typedef CallClass<void> GenericCallClass;
|
||||
|
||||
/**
|
||||
* @brief SH informs the loop in the hook manager about its status through this
|
||||
*/
|
||||
enum HookLoopStatus
|
||||
{
|
||||
HLS_Continue=0,
|
||||
HLS_Stop
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The main SourceHook interface
|
||||
*/
|
||||
@ -360,14 +351,15 @@ namespace SourceHook
|
||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For hook managers
|
||||
virtual META_RES &GetCurResRef() = 0; //!< Gets the reference to the current meta result
|
||||
virtual META_RES &GetPrevResRef() = 0; //!< Gets the reference to the previous meta result
|
||||
virtual META_RES &GetStatusRef() = 0; //!< Gets the reference to the status variable
|
||||
virtual void* &GetIfacePtrRef() = 0; //!< Gets the reference to the interface this pointer
|
||||
virtual void SetOrigRet(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRet(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual HookLoopStatus &GetStatusVarRef(IIface *pIface) = 0; //!< gets the reference to the hook status loop variable
|
||||
virtual void HookLoopDone() = 0;
|
||||
virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins
|
||||
virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits
|
||||
virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result
|
||||
virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result
|
||||
virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable
|
||||
virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer
|
||||
virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRetPtr(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit
|
||||
};
|
||||
}
|
||||
|
||||
@ -543,30 +535,31 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
rettype orig_ret; \
|
||||
rettype override_ret; \
|
||||
rettype plugin_ret; \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOrigRet(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
@ -574,9 +567,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
if (cur_res >= MRES_OVERRIDE) \
|
||||
{ \
|
||||
override_ret = plugin_ret; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(&override_ret); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(&override_ret); \
|
||||
} \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -595,6 +588,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
orig_ret = override_ret;
|
||||
|
||||
#define SH_RETURN() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd(); \
|
||||
return status >= MRES_OVERRIDE ? override_ret : orig_ret;
|
||||
|
||||
#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \
|
||||
@ -625,32 +619,33 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS_void(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
status = cur_res; \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -666,7 +661,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
}
|
||||
|
||||
#define SH_RETURN_void()
|
||||
#define SH_RETURN_void() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd();
|
||||
|
||||
#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \
|
||||
SH_SETUPCALLS_void(paramtypes, params) \
|
||||
|
@ -20,10 +20,10 @@
|
||||
// 1 - Initial revision
|
||||
// 2 - Changed to virtual functions for iterators and all queries
|
||||
// 3 - Added "hook loop status variable"
|
||||
// Future: Thread safe interface?
|
||||
// 4 - Reentrant
|
||||
|
||||
#define SH_IFACE_VERSION 3
|
||||
#define SH_IMPL_VERSION 2
|
||||
#define SH_IFACE_VERSION 4
|
||||
#define SH_IMPL_VERSION 3
|
||||
|
||||
#ifndef SH_GLOB_SHPTR
|
||||
#define SH_GLOB_SHPTR g_SHPtr
|
||||
@ -273,15 +273,6 @@ namespace SourceHook
|
||||
|
||||
typedef CallClass<void> GenericCallClass;
|
||||
|
||||
/**
|
||||
* @brief SH informs the loop in the hook manager about its status through this
|
||||
*/
|
||||
enum HookLoopStatus
|
||||
{
|
||||
HLS_Continue=0,
|
||||
HLS_Stop
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The main SourceHook interface
|
||||
*/
|
||||
@ -360,14 +351,15 @@ namespace SourceHook
|
||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For hook managers
|
||||
virtual META_RES &GetCurResRef() = 0; //!< Gets the reference to the current meta result
|
||||
virtual META_RES &GetPrevResRef() = 0; //!< Gets the reference to the previous meta result
|
||||
virtual META_RES &GetStatusRef() = 0; //!< Gets the reference to the status variable
|
||||
virtual void* &GetIfacePtrRef() = 0; //!< Gets the reference to the interface this pointer
|
||||
virtual void SetOrigRet(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRet(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual HookLoopStatus &GetStatusVarRef(IIface *pIface) = 0; //!< gets the reference to the hook status loop variable
|
||||
virtual void HookLoopDone() = 0;
|
||||
virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins
|
||||
virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits
|
||||
virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result
|
||||
virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result
|
||||
virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable
|
||||
virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer
|
||||
virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRetPtr(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit
|
||||
};
|
||||
}
|
||||
|
||||
@ -543,30 +535,31 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
rettype orig_ret; \
|
||||
rettype override_ret; \
|
||||
rettype plugin_ret; \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOrigRet(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
@ -574,9 +567,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
if (cur_res >= MRES_OVERRIDE) \
|
||||
{ \
|
||||
override_ret = plugin_ret; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(&override_ret); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(&override_ret); \
|
||||
} \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -595,6 +588,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
orig_ret = override_ret;
|
||||
|
||||
#define SH_RETURN() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd(); \
|
||||
return status >= MRES_OVERRIDE ? override_ret : orig_ret;
|
||||
|
||||
#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \
|
||||
@ -625,32 +619,33 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS_void(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
status = cur_res; \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -666,7 +661,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
}
|
||||
|
||||
#define SH_RETURN_void()
|
||||
#define SH_RETURN_void() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd();
|
||||
|
||||
#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \
|
||||
SH_SETUPCALLS_void(paramtypes, params) \
|
||||
|
165
sourcehook/sh_stack.h
Normal file
165
sourcehook/sh_stack.h
Normal file
@ -0,0 +1,165 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef __SH_STACK_H__
|
||||
#define __SH_STACK_H__
|
||||
|
||||
#define SH_STACK_DEFAULT_SIZE 4
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
// Vector
|
||||
template <class T> class CStack
|
||||
{
|
||||
T *m_Elements;
|
||||
size_t m_AllocatedSize;
|
||||
size_t m_UsedSize;
|
||||
public:
|
||||
friend class iterator;
|
||||
class iterator
|
||||
{
|
||||
CStack<T> *m_pParent;
|
||||
size_t m_Index;
|
||||
public:
|
||||
iterator(CStack<T> *pParent, size_t id) : m_pParent(pParent), m_Index(id)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(CStack<T> *pParent) : m_pParent(pParent), m_Index(0)
|
||||
{
|
||||
}
|
||||
|
||||
iterator() : m_pParent(NULL), m_Index(0)
|
||||
{
|
||||
}
|
||||
|
||||
T &operator *()
|
||||
{
|
||||
return m_pParent->m_Elements[m_Index];
|
||||
}
|
||||
const T &operator *() const
|
||||
{
|
||||
return m_pParent->m_Elements[m_Index];
|
||||
}
|
||||
|
||||
T * operator->()
|
||||
{
|
||||
return m_pParent->m_Elements + m_Index;
|
||||
}
|
||||
|
||||
const T * operator->() const
|
||||
{
|
||||
return m_pParent->m_Elements + m_Index;
|
||||
}
|
||||
|
||||
iterator & operator++() // preincrement
|
||||
{
|
||||
++m_Index;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator++(int) // postincrement
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator & operator--() // predecrement
|
||||
{
|
||||
--m_Index;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator--(int) // postdecrememnt
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const iterator & right) const
|
||||
{
|
||||
return (m_pParent == right.m_pParent && m_Index == right.m_Index);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator & right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
};
|
||||
CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]),
|
||||
m_AllocatedSize(SH_STACK_DEFAULT_SIZE),
|
||||
m_UsedSize(0)
|
||||
{
|
||||
assert(m_Elements);
|
||||
}
|
||||
CStack(size_t size) : m_Elements(new T[size]),
|
||||
m_AllocatedSize(size),
|
||||
m_UsedSize(0)
|
||||
{
|
||||
assert(m_Elements);
|
||||
}
|
||||
|
||||
~CStack()
|
||||
{
|
||||
if (m_Elements)
|
||||
delete [] m_Elements;
|
||||
}
|
||||
|
||||
bool push(const T &val)
|
||||
{
|
||||
if (m_UsedSize + 1 == m_AllocatedSize)
|
||||
{
|
||||
// zOHNOES! REALLOCATE!
|
||||
m_AllocatedSize *= 2;
|
||||
T *newElements = new T[m_AllocatedSize];
|
||||
if (!newElements)
|
||||
{
|
||||
m_AllocatedSize /= 2;
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||
newElements[i] = m_Elements[i];
|
||||
delete [] m_Elements;
|
||||
m_Elements = newElements;
|
||||
}
|
||||
m_Elements[m_UsedSize++] = val;
|
||||
return true;
|
||||
}
|
||||
void pop()
|
||||
{
|
||||
--m_UsedSize;
|
||||
}
|
||||
|
||||
T &front()
|
||||
{
|
||||
return m_Elements[m_UsedSize - 1];
|
||||
}
|
||||
|
||||
const T &front() const
|
||||
{
|
||||
return m_Elements[m_UsedSize - 1];
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(this, 0);
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return iterator(this, m_UsedSize);
|
||||
}
|
||||
};
|
||||
}; //namespace SourceHook
|
||||
|
||||
#endif
|
@ -365,8 +365,12 @@ namespace SourceHook
|
||||
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||
{
|
||||
// There are no hooks on this iface anymore...
|
||||
if (m_CurIface == static_cast<IIface*>(&(*iface_iter)))
|
||||
m_HLS = HLS_Stop;
|
||||
for (HookLoopInfoStack::iterator hli_iter = m_HLIStack.begin();
|
||||
hli_iter != m_HLIStack.end(); ++hli_iter)
|
||||
{
|
||||
if (hli_iter->pCurIface == static_cast<IIface*>(&(*iface_iter)))
|
||||
hli_iter->shouldContinue = false;
|
||||
}
|
||||
|
||||
iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter);
|
||||
if (vfnptr_iter->m_Ifaces.empty())
|
||||
@ -519,74 +523,80 @@ namespace SourceHook
|
||||
SetPluginPaused(plug, false);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::HookLoopBegin(IIface *pIface)
|
||||
{
|
||||
HookLoopInfo hli;
|
||||
hli.pCurIface = pIface;
|
||||
hli.shouldContinue = true;
|
||||
m_HLIStack.push(hli);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::HookLoopEnd()
|
||||
{
|
||||
m_HLIStack.pop();
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetRes(META_RES res)
|
||||
{
|
||||
m_CurRes = res;
|
||||
*m_HLIStack.front().pCurRes = res;
|
||||
}
|
||||
|
||||
META_RES CSourceHookImpl::GetPrevRes()
|
||||
{
|
||||
return m_PrevRes;
|
||||
return *m_HLIStack.front().pPrevRes;
|
||||
}
|
||||
|
||||
META_RES CSourceHookImpl::GetStatus()
|
||||
{
|
||||
return m_Status;
|
||||
return *m_HLIStack.front().pStatus;
|
||||
}
|
||||
|
||||
const void *CSourceHookImpl::GetOrigRet()
|
||||
{
|
||||
return m_OrigRet;
|
||||
return m_HLIStack.front().pOrigRet;
|
||||
}
|
||||
|
||||
const void *CSourceHookImpl::GetOverrideRet()
|
||||
{
|
||||
return m_OverrideRet;
|
||||
}
|
||||
|
||||
META_RES &CSourceHookImpl::GetCurResRef()
|
||||
{
|
||||
return m_CurRes;
|
||||
}
|
||||
|
||||
META_RES &CSourceHookImpl::GetPrevResRef()
|
||||
{
|
||||
return m_PrevRes;
|
||||
}
|
||||
|
||||
META_RES &CSourceHookImpl::GetStatusRef()
|
||||
{
|
||||
return m_Status;
|
||||
}
|
||||
|
||||
void * &CSourceHookImpl::GetIfacePtrRef()
|
||||
{
|
||||
return m_IfacePtr;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetOrigRet(const void *ptr)
|
||||
{
|
||||
m_OrigRet = ptr;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetOverrideRet(const void *ptr)
|
||||
{
|
||||
m_OverrideRet = ptr;
|
||||
return m_HLIStack.front().pOverrideRet;
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::GetIfacePtr()
|
||||
{
|
||||
return m_IfacePtr;
|
||||
return *m_HLIStack.front().pIfacePtrPtr;
|
||||
}
|
||||
|
||||
HookLoopStatus &CSourceHookImpl::GetStatusVarRef(IIface *pIface)
|
||||
void CSourceHookImpl::SetCurResPtr(META_RES *mres)
|
||||
{
|
||||
m_CurIface = pIface;
|
||||
return m_HLS;
|
||||
m_HLIStack.front().pCurRes = mres;
|
||||
}
|
||||
void CSourceHookImpl::HookLoopDone()
|
||||
|
||||
void CSourceHookImpl::SetPrevResPtr(META_RES *mres)
|
||||
{
|
||||
m_CurIface = NULL;
|
||||
m_HLIStack.front().pPrevRes = mres;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetStatusPtr(META_RES *mres)
|
||||
{
|
||||
m_HLIStack.front().pStatus = mres;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetIfacePtrPtr(void **pp)
|
||||
{
|
||||
m_HLIStack.front().pIfacePtrPtr = pp;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetOrigRetPtr(const void *ptr)
|
||||
{
|
||||
m_HLIStack.front().pOrigRet = ptr;
|
||||
}
|
||||
void CSourceHookImpl::SetOverrideRetPtr(const void *ptr)
|
||||
{
|
||||
m_HLIStack.front().pOverrideRet = ptr;
|
||||
}
|
||||
bool CSourceHookImpl::ShouldContinue()
|
||||
{
|
||||
return m_HLIStack.front().shouldContinue;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
@ -20,10 +20,10 @@
|
||||
// 1 - Initial revision
|
||||
// 2 - Changed to virtual functions for iterators and all queries
|
||||
// 3 - Added "hook loop status variable"
|
||||
// Future: Thread safe interface?
|
||||
// 4 - Reentrant
|
||||
|
||||
#define SH_IFACE_VERSION 3
|
||||
#define SH_IMPL_VERSION 2
|
||||
#define SH_IFACE_VERSION 4
|
||||
#define SH_IMPL_VERSION 3
|
||||
|
||||
#ifndef SH_GLOB_SHPTR
|
||||
#define SH_GLOB_SHPTR g_SHPtr
|
||||
@ -273,15 +273,6 @@ namespace SourceHook
|
||||
|
||||
typedef CallClass<void> GenericCallClass;
|
||||
|
||||
/**
|
||||
* @brief SH informs the loop in the hook manager about its status through this
|
||||
*/
|
||||
enum HookLoopStatus
|
||||
{
|
||||
HLS_Continue=0,
|
||||
HLS_Stop
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The main SourceHook interface
|
||||
*/
|
||||
@ -360,14 +351,15 @@ namespace SourceHook
|
||||
virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For hook managers
|
||||
virtual META_RES &GetCurResRef() = 0; //!< Gets the reference to the current meta result
|
||||
virtual META_RES &GetPrevResRef() = 0; //!< Gets the reference to the previous meta result
|
||||
virtual META_RES &GetStatusRef() = 0; //!< Gets the reference to the status variable
|
||||
virtual void* &GetIfacePtrRef() = 0; //!< Gets the reference to the interface this pointer
|
||||
virtual void SetOrigRet(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRet(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual HookLoopStatus &GetStatusVarRef(IIface *pIface) = 0; //!< gets the reference to the hook status loop variable
|
||||
virtual void HookLoopDone() = 0;
|
||||
virtual void HookLoopBegin(IIface *pIface) = 0; //!< Should be called when a hook loop begins
|
||||
virtual void HookLoopEnd() = 0; //!< Should be called when a hook loop exits
|
||||
virtual void SetCurResPtr(META_RES *mres) = 0; //!< Sets pointer to the current meta result
|
||||
virtual void SetPrevResPtr(META_RES *mres) = 0; //!< Sets pointer to previous meta result
|
||||
virtual void SetStatusPtr(META_RES *mres) = 0; //!< Sets pointer to the status variable
|
||||
virtual void SetIfacePtrPtr(void **pp) = 0; //!< Sets pointer to the interface this pointer
|
||||
virtual void SetOrigRetPtr(const void *ptr) = 0; //!< Sets the original return pointer
|
||||
virtual void SetOverrideRetPtr(const void *ptr) = 0; //!< Sets the override result pointer
|
||||
virtual bool ShouldContinue() = 0; //!< Returns false if the hook loop should exit
|
||||
};
|
||||
}
|
||||
|
||||
@ -543,30 +535,31 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return (reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
rettype orig_ret; \
|
||||
rettype override_ret; \
|
||||
rettype plugin_ret; \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOrigRet(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL);
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(reinterpret_cast<void*>(&orig_ret)); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
plugin_ret = reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
@ -574,9 +567,9 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
if (cur_res >= MRES_OVERRIDE) \
|
||||
{ \
|
||||
override_ret = plugin_ret; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(&override_ret); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(&override_ret); \
|
||||
} \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -595,6 +588,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
orig_ret = override_ret;
|
||||
|
||||
#define SH_RETURN() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd(); \
|
||||
return status >= MRES_OVERRIDE ? override_ret : orig_ret;
|
||||
|
||||
#define SH_HANDLEFUNC(ifacetype, ifacefunc, paramtypes, params, rettype) \
|
||||
@ -625,32 +619,33 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
return; \
|
||||
} \
|
||||
/* 2) Declare some vars and set it up */ \
|
||||
SH_GLOB_SHPTR->HookLoopBegin(ifinfo); \
|
||||
IHookList *prelist = ifinfo->GetPreHooks(); \
|
||||
IHookList *postlist = ifinfo->GetPostHooks(); \
|
||||
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
|
||||
HookLoopStatus &hls = SH_GLOB_SHPTR->GetStatusVarRef(ifinfo); \
|
||||
hls = HLS_Continue; \
|
||||
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
|
||||
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
|
||||
void* &ifptr = SH_GLOB_SHPTR->GetIfacePtrRef(); \
|
||||
status = MRES_IGNORED; \
|
||||
SH_GLOB_SHPTR->SetOverrideRet(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRet(NULL);
|
||||
META_RES status = MRES_IGNORED; \
|
||||
META_RES prev_res; \
|
||||
META_RES cur_res; \
|
||||
SH_GLOB_SHPTR->SetStatusPtr(&status); \
|
||||
SH_GLOB_SHPTR->SetPrevResPtr(&prev_res); \
|
||||
SH_GLOB_SHPTR->SetCurResPtr(&cur_res); \
|
||||
void* ifptr; \
|
||||
SH_GLOB_SHPTR->SetIfacePtrPtr(&ifptr); \
|
||||
SH_GLOB_SHPTR->SetOverrideRetPtr(NULL); \
|
||||
SH_GLOB_SHPTR->SetOrigRetPtr(NULL);
|
||||
|
||||
#define SH_CALL_HOOKS_void(post, params) \
|
||||
if (hls == HLS_Continue) \
|
||||
if (SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
prev_res = MRES_IGNORED; \
|
||||
for (AutoHookIter iter(post##list); !iter.End(); iter.Next()) \
|
||||
{ \
|
||||
cur_res = MRES_IGNORED; \
|
||||
ifptr = reinterpret_cast<void*>(reinterpret_cast<char*>(this) - iter.ThisPtrOffs()); \
|
||||
hls = HLS_Continue; \
|
||||
reinterpret_cast<CSHDelegate<FD>*>(iter.Handler())->GetDeleg() params; \
|
||||
prev_res = cur_res; \
|
||||
if (cur_res > status) \
|
||||
status = cur_res; \
|
||||
if (hls == HLS_Stop) \
|
||||
if (!SH_GLOB_SHPTR->ShouldContinue()) \
|
||||
{ \
|
||||
iter.SetToZero(); \
|
||||
break; \
|
||||
@ -666,7 +661,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
(reinterpret_cast<EmptyClass*>(this)->*mfp)params; \
|
||||
}
|
||||
|
||||
#define SH_RETURN_void()
|
||||
#define SH_RETURN_void() \
|
||||
SH_GLOB_SHPTR->HookLoopEnd();
|
||||
|
||||
#define SH_HANDLEFUNC_void(ifacetype, ifacefunc, paramtypes, params) \
|
||||
SH_SETUPCALLS_void(paramtypes, params) \
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "sh_list.h"
|
||||
#include "sh_vector.h"
|
||||
#include "sh_tinyhash.h"
|
||||
#include "sh_stack.h"
|
||||
|
||||
// Set this to 1 to enable runtime code generation (faster)
|
||||
// (unused at the moment, but may come back, so I'm leaving it in here!)
|
||||
@ -217,6 +218,21 @@ namespace SourceHook
|
||||
Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses
|
||||
HookManInfoList m_HookMans; //!< A list of hook managers
|
||||
|
||||
struct HookLoopInfo
|
||||
{
|
||||
META_RES *pStatus;
|
||||
META_RES *pPrevRes;
|
||||
META_RES *pCurRes;
|
||||
|
||||
bool shouldContinue;
|
||||
|
||||
IIface *pCurIface;
|
||||
const void *pOrigRet;
|
||||
const void *pOverrideRet;
|
||||
void **pIfacePtrPtr;
|
||||
};
|
||||
typedef CStack<HookLoopInfo> HookLoopInfoStack;
|
||||
|
||||
/**
|
||||
* @brief Finds a hook manager for a function based on a text-prototype, a vtable offset and a vtable index
|
||||
*/
|
||||
@ -229,12 +245,7 @@ namespace SourceHook
|
||||
|
||||
void SetPluginPaused(Plugin plug, bool paused);
|
||||
|
||||
META_RES m_Status, m_PrevRes, m_CurRes;
|
||||
HookLoopStatus m_HLS;
|
||||
IIface *m_CurIface;
|
||||
const void *m_OrigRet;
|
||||
const void *m_OverrideRet;
|
||||
void *m_IfacePtr;
|
||||
HookLoopInfoStack m_HLIStack;
|
||||
public:
|
||||
CSourceHookImpl();
|
||||
virtual ~CSourceHookImpl();
|
||||
@ -341,14 +352,15 @@ namespace SourceHook
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For hook managers
|
||||
virtual META_RES &GetCurResRef(); //!< Gets the reference to the current meta result
|
||||
virtual META_RES &GetPrevResRef(); //!< Gets the reference to the previous meta result
|
||||
virtual META_RES &GetStatusRef(); //!< Gets the reference to the status variable
|
||||
virtual void* &GetIfacePtrRef(); //!< Gets the reference to the iface ptr
|
||||
virtual void SetOrigRet(const void *ptr); //!< Sets the original return pointer
|
||||
virtual void SetOverrideRet(const void *ptr); //!< Sets the override result pointer
|
||||
HookLoopStatus &GetStatusVarRef(IIface *pIface);
|
||||
void HookLoopDone();
|
||||
void HookLoopBegin(IIface *pIface); //!< Should be called when a hook loop begins
|
||||
void HookLoopEnd(); //!< Should be called when a hook loop exits
|
||||
void SetCurResPtr(META_RES *mres); //!< Sets pointer to the current meta result
|
||||
void SetPrevResPtr(META_RES *mres); //!< Sets pointer to previous meta result
|
||||
void SetStatusPtr(META_RES *mres); //!< Sets pointer to the status variable
|
||||
void SetIfacePtrPtr(void **pp); //!< Sets pointer to the interface this pointer
|
||||
void SetOrigRetPtr(const void *ptr); //!< Sets the original return pointer
|
||||
void SetOverrideRetPtr(const void *ptr); //!< Sets the override result pointer
|
||||
bool ShouldContinue(); //!< Returns false if the hook loop should exit
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -275,6 +275,9 @@
|
||||
<File
|
||||
RelativePath="..\sh_list.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sh_stack.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sh_string.h">
|
||||
</File>
|
||||
|
@ -17,13 +17,11 @@ namespace
|
||||
SH_DECL_HOOK0_void(zomg_lolz, zomg, SH_NOATTRIB, 0);
|
||||
void Handler()
|
||||
{
|
||||
printf("H1\n");
|
||||
SH_REMOVE_HOOK_STATICFUNC(zomg_lolz, zomg, reinterpret_cast<zomg_lolz*>(META_IFACEPTR),
|
||||
Handler, false);
|
||||
}
|
||||
void Handler2()
|
||||
{
|
||||
printf("H2\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,5 +134,23 @@ namespace
|
||||
virtual void Dump() { \
|
||||
std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << std::endl; } \
|
||||
}
|
||||
|
||||
#define MAKE_STATE_3(name, p1_type, p2_type, p3_type) struct name : State { \
|
||||
p1_type m_Param1; \
|
||||
p2_type m_Param2; \
|
||||
p3_type m_Param3; \
|
||||
name(p1_type param1, p2_type param2, p3_type param3) : m_Param1(param1), m_Param2(param2), m_Param3(param3) {} \
|
||||
virtual bool IsEqual(State *other) { \
|
||||
name *other2 = dynamic_cast<name*>(other); \
|
||||
if (!other2) \
|
||||
return false; \
|
||||
return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2 && other2->m_Param3 == m_Param3;\
|
||||
} \
|
||||
virtual void Dump() { \
|
||||
std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << "; Param3=" << m_Param3 << std::endl; } \
|
||||
}
|
||||
|
||||
#define CHECK_COND(c, err) if (!(c)) { error = err; return false; }
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
#include <string>
|
||||
#include "sh_list.h"
|
||||
#include "sh_tinyhash.h"
|
||||
#include "testevents.h"
|
||||
|
||||
// TEST LIST
|
||||
// Tests sh_list, sh_tinyhash, sh_vector
|
||||
|
||||
// :TODO: vector test
|
||||
|
||||
#define CHECK_COND(c, err) if (!(c)) { error = err; return false; }
|
||||
// :TODO: stack test
|
||||
|
||||
namespace
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user