SourceHook tests pass again! Added test for list (and a small bit of tinyhash). Woot.

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40112
This commit is contained in:
Pavol Marko 2005-09-23 20:14:10 +00:00
parent 5ed98f9a46
commit 46e9986a0e
12 changed files with 6209 additions and 55 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,779 @@
/* ======== SourceHook ========
* Copyright (C) 2004-2005 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): Pavol "PM OnoTo" Marko
* ============================
*/
/**
* @brief This file provides a way for getting information about a member function.
* @file sh_memfuncinfo.h
*/
#ifndef __SHINT_MEMFUNC_INFO_H__
#define __SHINT_MEMFUNC_INFO_H__
namespace SourceHook
{
// Don Clugston:
// implicit_cast< >
// I believe this was originally going to be in the C++ standard but
// was left out by accident. It's even milder than static_cast.
// I use it instead of static_cast<> to emphasize that I'm not doing
// anything nasty.
// Usage is identical to static_cast<>
template <class OutputClass, class InputClass>
inline OutputClass implicit_cast(InputClass input){
return input;
}
struct MemFuncInfo
{
bool isVirtual; // Is the function virtual?
int thisptroffs; // The this pointer the function expects to be called with
// If -1, you need to call the GetFuncInfo_GetThisPtr function
int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...)
int vtbloffs; // The vtable pointer
};
// Ideas by Don Clugston.
// Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp
template<int N> struct MFI_Impl
{
template<class MFP> static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out)
{
static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000];
}
};
# if SH_COMP == SH_COMP_GCC
template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16
{
struct GCC_MemFunPtr
{
union
{
void *funcadr; // always even
intptr_t vtable_index_plus1; // = vindex+1, always odd
};
intptr_t delta;
};
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
{
GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp;
out.thisptroffs = mfp_detail->delta;
if (mfp_detail->vtable_index_plus1 & 1)
{
out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE;
out.vtbloffs = 0;
out.isVirtual = true;
}
else
out.isVirtual = false;
}
};
# elif SH_COMP == SH_COMP_MSVC
namespace
{
int MFI_GetVtblOffset(void *mfp)
{
unsigned char *addr = (unsigned char*)mfp;
if (*addr == 0xE9) // Jmp
{
// May or may not be!
// Check where it'd jump
addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1);
}
// Check whether it's a virtual function call
// They look like this:
// 004125A0 8B 01 mov eax,dword ptr [ecx]
// 004125A2 FF 60 04 jmp dword ptr [eax+4]
// ==OR==
// 00411B80 8B 01 mov eax,dword ptr [ecx]
// 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h]
// However, for vararg functions, they look like this:
// 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4]
// 0048F0B4 8B 00 mov eax,dword ptr [eax]
// 0048F0B6 FF 60 08 jmp dword ptr [eax+8]
// ==OR==
// 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4]
// 0048F0B4 8B 00 mov eax,dword ptr [eax]
// 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h]
// With varargs, the this pointer is passed as if it was the first argument
bool ok = false;
if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 &&
addr[4] == 0x8B && addr[5] == 0x00)
{
addr += 6;
ok = true;
}
else if (addr[0] == 0x8B && addr[1] == 0x01)
{
addr += 2;
ok = true;
}
if (!ok)
return -1;
if (*addr++ == 0xFF)
{
if (*addr == 0x60)
{
return *++addr / 4;
}
else if (*addr == 0xA0)
{
return *((unsigned int*)++addr) / 4;
}
else if (*addr == 0x20)
return 0;
else
return -1;
}
return -1;
}
}
template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones
{
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
{
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
out.isVirtual = out.vtblindex >= 0 ? true : false;
out.thisptroffs = 0;
out.vtbloffs = 0;
}
};
template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones!
{
struct MSVC_MemFunPtr2
{
void *funcadr;
int delta;
};
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
{
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
out.isVirtual = out.vtblindex >= 0 ? true : false;
out.thisptroffs = reinterpret_cast<MSVC_MemFunPtr2*>(&mfp)->delta;
out.vtbloffs = 0;
}
};
// By Don Clugston, adapted
template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG
{
class __single_inheritance GenericClass;
class GenericClass {};
struct MicrosoftVirtualMFP {
void (GenericClass::*codeptr)(); // points to the actual member function
int delta; // #bytes to be added to the 'this' pointer
int vtable_index; // or 0 if no virtual inheritance
};
struct GenericVirtualClass : virtual public GenericClass
{
typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
GenericVirtualClass * GetThis() { return this; }
};
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
{
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
out.isVirtual = out.vtblindex >= 0 ? true : false;
// This pointer
/*
union {
MFP func;
GenericClass* (T::*ProbeFunc)();
MicrosoftVirtualMFP s;
} u;
u.func = mfp;
union {
GenericVirtualClass::ProbePtrType virtfunc;
MicrosoftVirtualMFP s;
} u2;
// Check that the horrible_cast<>s will work
typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s)
&& sizeof(mfp)==sizeof(u.ProbeFunc)
&& sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
// Unfortunately, taking the address of a MF prevents it from being inlined, so
// this next line can't be completely optimised away by the compiler.
u2.virtfunc = &GenericVirtualClass::GetThis;
u.s.codeptr = u2.s.codeptr;
out.thisptroffs = (reinterpret_cast<T*>(NULL)->*u.ProbeFunc)();
*/
out.thisptroffs = -1;
out.vtbloffs = 0;
}
};
// Don: Nasty hack for Microsoft and Intel (IA32 and Itanium)
// unknown_inheritance classes go here
// This is probably the ugliest bit of code I've ever written. Look at the casts!
// There is a compiler bug in MSVC6 which prevents it from using this code.
template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN
{
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
{
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
out.isVirtual = out.vtblindex >= 0 ? true : false;
// The member function pointer is 16 bytes long. We can't use a normal cast, but
// we can use a union to do the conversion.
union {
MFP func;
// In VC++ and ICL, an unknown_inheritance member pointer
// is internally defined as:
struct {
void *m_funcaddress; // points to the actual member function
int delta; // #bytes to be added to the 'this' pointer
int vtordisp; // #bytes to add to 'this' to find the vtable
int vtable_index; // or 0 if no virtual inheritance
} s;
} u;
// Check that the horrible_cast will work
typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1];
u.func = mfp;
int virtual_delta = 0;
if (u.s.vtable_index) { // Virtual inheritance is used
/*
// First, get to the vtable.
// It is 'vtordisp' bytes from the start of the class.
int * vtable = *reinterpret_cast<int **>(
reinterpret_cast<char *>(thisptr) + u.s.vtordisp );
// 'vtable_index' tells us where in the table we should be looking.
virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
// The int at 'virtual_delta' gives us the amount to add to 'this'.
// Finally we can add the three components together. Phew!
out.thisptr = reinterpret_cast<void *>(
reinterpret_cast<char *>(thisptr) + u.s.delta + virtual_delta);
*/
out.vtbloffs = u.s.vtordisp;
out.thisptroffs = -1;
}
else
{
out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta;
out.thisptroffs = u.s.delta;
}
};
};
# else
# error Unsupported compiler
# endif
// This version does not take a this pointer
// Useful for hookdecls, as they ensure that mfp is correct through a static_cast
template<class X> inline void GetFuncInfo(X mfp, MemFuncInfo &out)
{
MFI_Impl<sizeof(mfp)>::GetFuncInfo(mfp, out);
}
// Versions which do take a this
template<class X, class Y, class RetType>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out)
{
RetType(Y::*mfp2)() = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out)
{
RetType(Y::*mfp2)() const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
template<class X, class Y, class RetType>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out)
{
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp;
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
}
#endif
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,10 @@
#define SH_GLOB_PLUGPTR g_PLID
#endif
#ifdef SH_DEBUG
# include <stdio.h>
# include <stdlib.h>
# define SH_ASSERT__(x, info, file, line, func) \
((printf("SOURCEHOOK DEBUG ASSERTION FAILED:\n %s:%u(%s): %s\n", file, line, func, info), true) ? (abort(), 0) : 0)
# define SH_ASSERT(x, info) if (!(x)) SH_ASSERT__(x, info, __FILE__, __LINE__, __FUNCTION__)
@ -68,10 +71,9 @@
#include "FastDelegate.h"
#include "sh_memfuncinfo.h"
#include "sh_memory.h"
#include <list>
#include <vector>
#include <map>
#include <algorithm>
#include "sh_list.h"
#include "sh_vector.h"
#include "sh_tinyhash.h"
// Good old metamod!
@ -185,8 +187,8 @@ namespace SourceHook
int thisptr_offs; //!< This pointer offset
};
void *ptr; //!< Pointer to the interface instance
SourceHook::List<Hook> hooks_pre; //!< A list of pre-hooks
SourceHook::List<Hook> hooks_post; //!< A list of post-hooks
List<Hook> hooks_pre; //!< A list of pre-hooks
List<Hook> hooks_post; //!< A list of post-hooks
bool operator ==(void *other) const
{
return ptr == other;
@ -196,7 +198,7 @@ namespace SourceHook
void *vfnptr; //!< Pointer to the function
void *orig_entry; //!< The original vtable entry
typedef SourceHook::List<Iface> IfaceList;
typedef List<Iface> IfaceList;
typedef IfaceList::iterator IfaceListIter;
IfaceList ifaces; //!< List of interface pointers
@ -214,7 +216,7 @@ namespace SourceHook
void *hookfunc_vfnptr; //!< Pointer to the hookfunc impl
typedef SourceHook::List<VfnPtr> VfnPtrList;
typedef List<VfnPtr> VfnPtrList;
typedef VfnPtrList::iterator VfnPtrListIter;
VfnPtrList vfnptrs; //!< List of hooked interfaces
};
@ -237,6 +239,8 @@ namespace SourceHook
class ISourceHook
{
public:
virtual ~ISourceHook()
{ }
/**
* @brief Return interface version
*/
@ -467,8 +471,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
void *ourvfnptr = reinterpret_cast<void*>( \
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
\
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->find(ms_HI->vfnptrs.begin(), \
ms_HI->vfnptrs.end(), ourvfnptr); \
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
if (vfptriter == ms_HI->vfnptrs.end()) \
{ \
/* Bleh? Should be impossible! */ \
@ -476,7 +479,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
} \
HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \
/* 2) Find the iface */ \
HookManagerInfo::VfnPtr::IfaceListIter ifiter = ms_HI->find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \
HookManagerInfo::VfnPtr::IfaceListIter ifiter = vfnptr.ifaces.find(this); \
if (ifiter == vfnptr.ifaces.end()) \
{ \
/* The iface info was not found. Redirect the call to the original function. */ \
@ -486,8 +489,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
} \
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
/* 2) Declare some vars and set it up */ \
SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
rettype orig_ret; \
rettype override_ret; \
rettype plugin_ret; \
@ -501,7 +504,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
#define SH_CALL_HOOKS(post, params) \
prev_res = MRES_IGNORED; \
for (SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
{ \
if (hiter->paused) continue; \
cur_res = MRES_IGNORED; \
@ -544,8 +547,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
void *ourvfnptr = reinterpret_cast<void*>( \
*reinterpret_cast<void***>(reinterpret_cast<char*>(this) + ms_HI->vtbl_offs) + ms_HI->vtbl_idx); \
\
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->find(ms_HI->vfnptrs.begin(), \
ms_HI->vfnptrs.end(), ourvfnptr); \
HookManagerInfo::VfnPtrListIter vfptriter = ms_HI->vfnptrs.find(ourvfnptr); \
if (vfptriter == ms_HI->vfnptrs.end()) \
{ \
/* Bleh? Should be impossible! */ \
@ -553,7 +555,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
} \
HookManagerInfo::VfnPtr &vfnptr = *vfptriter; \
/* 2) Find the iface */ \
HookManagerInfo::VfnPtr::IfaceListIter ifiter = ms_HI->find(vfnptr.ifaces.begin(), vfnptr.ifaces.end(), this); \
HookManagerInfo::VfnPtr::IfaceListIter ifiter = vfnptr.ifaces.find(this); \
if (ifiter == vfnptr.ifaces.end()) \
{ \
/* The iface info was not found. Redirect the call to the original function. */ \
@ -564,8 +566,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
} \
HookManagerInfo::VfnPtr::Iface &ci = *ifiter; \
/* 2) Declare some vars and set it up */ \
SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
List<HookManagerInfo::VfnPtr::Iface::Hook> &prelist = ci.hooks_pre; \
List<HookManagerInfo::VfnPtr::Iface::Hook> &postlist = ci.hooks_post; \
META_RES &cur_res = SH_GLOB_SHPTR->GetCurResRef(); \
META_RES &prev_res = SH_GLOB_SHPTR->GetPrevResRef(); \
META_RES &status = SH_GLOB_SHPTR->GetStatusRef(); \
@ -575,7 +577,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
#define SH_CALL_HOOKS_void(post, params) \
prev_res = MRES_IGNORED; \
for (SourceHook::List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
for (List<HookManagerInfo::VfnPtr::Iface::Hook>::iterator hiter = post##list.begin(); hiter != post##list.end(); ++hiter) \
{ \
if (hiter->paused) continue; \
cur_res = MRES_IGNORED; \

View File

@ -126,12 +126,22 @@ public:
{
m_This = where.m_This;
}
//pre decrement
iterator & operator--()
{
if (m_This)
m_This = m_This->prev;
return *this;
}
//post decrement
iterator operator--(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->prev;
return old;
}
//pre increment
iterator & operator++()
{
@ -147,7 +157,8 @@ public:
m_This = m_This->next;
return old;
}
T & operator * () const
const T & operator * () const
{
return m_This->obj;
}
@ -155,10 +166,16 @@ public:
{
return m_This->obj;
}
T * operator -> () const
T * operator -> ()
{
return &(m_This->obj);
}
const T * operator -> () const
{
return &(m_This->obj);
}
bool operator != (const iterator &where) const
{
return (m_This != where.m_This);
@ -238,6 +255,7 @@ public:
}
List & operator =(List &src)
{
clear();
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
push_back( (*iter) );

View File

@ -42,10 +42,40 @@ namespace SourceHook
};
typedef List<THashNode *> * NodePtr;
public:
THash() : m_numBuckets(0), m_Buckets(NULL)
THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f)
{
_Refactor();
}
THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]),
m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed)
{
for (size_t i=0; i<m_numBuckets; i++)
m_Buckets[i] = NULL;
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
_FindOrInsert(iter->key)->val = iter->val;
}
void operator=(const THash &other)
{
clear();
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
_FindOrInsert(iter->key)->val = iter->val;
}
~THash()
{
if (m_Buckets)
delete [] m_Buckets;
}
void clear()
{
if (m_Buckets)
delete [] m_Buckets;
m_Buckets = NULL;
m_numBuckets = 0;
m_percentUsed = 0.0f;
_Refactor();
}
size_t GetBuckets()
{
return m_numBuckets;
@ -135,14 +165,15 @@ namespace SourceHook
}
public:
friend class iterator;
friend class const_iterator;
class iterator
{
friend class THash;
public:
iterator() : hash(NULL), end(true)
iterator() : curbucket(-1), hash(NULL), end(true)
{
};
iterator(THash *h) : hash(h), end(false)
iterator(THash *h) : curbucket(-1), hash(h), end(false)
{
if (!h->m_Buckets)
end = true;
@ -162,7 +193,7 @@ namespace SourceHook
_Inc();
return old;
}
THashNode & operator * () const
const THashNode & operator * () const
{
return *(*iter);
}
@ -170,7 +201,7 @@ namespace SourceHook
{
return *(*iter);
}
THashNode * operator ->() const
const THashNode * operator ->() const
{
return (*iter);
}
@ -197,7 +228,7 @@ namespace SourceHook
private:
void _Inc()
{
if (end || !hash || curbucket >= hash->m_numBuckets)
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{
@ -242,6 +273,105 @@ namespace SourceHook
THash *hash;
bool end;
};
class const_iterator
{
friend class THash;
public:
const_iterator() : curbucket(-1), hash(NULL), end(true)
{
};
const_iterator(const THash *h) : curbucket(-1), hash(h), end(false)
{
if (!h->m_Buckets)
end = true;
else
_Inc();
};
//pre increment
const_iterator & operator++()
{
_Inc();
return *this;
}
//post increment
const_iterator operator++(int)
{
iterator old(*this);
_Inc();
return old;
}
const THashNode & operator * () const
{
return *(*iter);
}
const THashNode * operator ->() const
{
return (*iter);
}
bool operator ==(const const_iterator &where) const
{
if (where.hash == this->hash
&& where.end == this->end
&&
(this->end ||
((where.curbucket == this->curbucket)
&& (where.iter == iter))
))
return true;
return false;
}
bool operator !=(const const_iterator &where) const
{
return !( (*this) == where );
}
private:
void _Inc()
{
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{
for (int i=0; i<(int)hash->m_numBuckets; i++)
{
if (hash->m_Buckets[i])
{
iter = hash->m_Buckets[i]->begin();
if (iter == hash->m_Buckets[i]->end())
continue;
curbucket = i;
break;
}
}
if (curbucket < 0)
end = true;
} else {
if (iter != hash->m_Buckets[curbucket]->end())
iter++;
if (iter == hash->m_Buckets[curbucket]->end())
{
int oldbucket = curbucket;
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
{
if (hash->m_Buckets[i])
{
iter = hash->m_Buckets[i]->begin();
if (iter == hash->m_Buckets[i]->end())
continue;
curbucket = i;
break;
}
}
if (curbucket == oldbucket)
end = true;
}
}
}
private:
int curbucket;
typename SourceHook::List<THashNode *>::iterator iter;
const THash *hash;
bool end;
};
public:
iterator begin()
{
@ -253,6 +383,18 @@ namespace SourceHook
iter.hash = this;
return iter;
}
const_iterator begin() const
{
return const_iterator(this);
}
const_iterator end() const
{
const_iterator iter;
iter.hash = this;
return iter;
}
template <typename U>
iterator find(const U & u) const
{

View File

@ -27,7 +27,10 @@
#define SH_GLOB_PLUGPTR g_PLID
#endif
#ifdef SH_DEBUG
# include <stdio.h>
# include <stdlib.h>
# define SH_ASSERT__(x, info, file, line, func) \
((printf("SOURCEHOOK DEBUG ASSERTION FAILED:\n %s:%u(%s): %s\n", file, line, func, info), true) ? (abort(), 0) : 0)
# define SH_ASSERT(x, info) if (!(x)) SH_ASSERT__(x, info, __FILE__, __LINE__, __FUNCTION__)
@ -184,8 +187,8 @@ namespace SourceHook
int thisptr_offs; //!< This pointer offset
};
void *ptr; //!< Pointer to the interface instance
List<Hook> hooks_pre; //!< A list of pre-hooks
List<Hook> hooks_post; //!< A list of post-hooks
List<Hook> hooks_pre; //!< A list of pre-hooks
List<Hook> hooks_post; //!< A list of post-hooks
bool operator ==(void *other) const
{
return ptr == other;
@ -236,6 +239,8 @@ namespace SourceHook
class ISourceHook
{
public:
virtual ~ISourceHook()
{ }
/**
* @brief Return interface version
*/

View File

@ -1,14 +1,15 @@
// Hello BAIL!
// hello pm how are you
// I'm fine, what about you?
// This is a test file
#include <stdio.h>
#include <iostream>
#include <string>
#include <list>
#include <stdlib.h>
#include <time.h>
#include "sh_tinyhash.h"
#include "sh_list.h"
#include "sourcehook_impl.h"
using namespace std;
@ -21,7 +22,7 @@ class Test
TestProto m_Func;
std::string m_Name;
static std::list<Test *> ms_Tests;
static SourceHook::List<Test *> ms_Tests;
public:
Test(TestProto func, const char *name) : m_Func(func), m_Name(name)
{
@ -46,7 +47,7 @@ public:
static void DoTests()
{
int passed=0, failed=0;
for (std::list<Test*>::iterator iter = ms_Tests.begin(); iter != ms_Tests.end(); ++iter)
for (SourceHook::List<Test*>::iterator iter = ms_Tests.begin(); iter != ms_Tests.end(); ++iter)
{
if ((**iter)())
++passed;
@ -58,40 +59,22 @@ public:
}
};
std::list<Test *> Test::ms_Tests;
SourceHook::List<Test *> Test::ms_Tests;
#define DO_TEST(x) \
bool Test##x(std::string &error); \
Test g_Test##x(Test##x, #x);
DO_TEST(List);
DO_TEST(Basic);
DO_TEST(VafmtAndOverload);
DO_TEST(ThisPtrOffs);
DO_TEST(PlugSys);
DO_TEST(Bail);
template <>
int SourceHook::HashFunction<int>(const int & k)
{
return k;
}
template <>
int SourceHook::Compare<int>(const int & v1, const int & v2)
{
if (v1 == v2)
return 0;
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}
int main(int argc, char *argv[])
{
std::string error;
int passed=0, failed=0;
g_Verbose = argc > 1 && strcmp(argv[1], "-v") == 0;

View File

@ -39,4 +39,4 @@ namespace
IGaben *g_Gabgab;
}
extern void *___testbail_gabgab;
extern void *___testbail_gabgab;

View File

@ -20,4 +20,4 @@ void ___TestBail2()
SH_REMOVE_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams0_Handler, false);
g_Gabgab->EatYams();
}
}

View File

@ -0,0 +1,165 @@
#include <string>
#include "sh_list.h"
#include "sh_tinyhash.h"
// TEST LIST
// Tests sh_list, sh_tinyhash, sh_vector
// :TODO: vector test
#define CHECK_COND(c, err) if (!(c)) { error = err; return false; }
namespace
{
struct Hmm
{
Hmm *m_This;
int m_Int;
Hmm(const Hmm &other) : m_This(this), m_Int(other.m_Int)
{
}
Hmm(int i) : m_This(this), m_Int(i)
{
}
Hmm() : m_This(this), m_Int(0)
{
}
void operator = (const Hmm &other)
{
m_Int = other.m_Int;
}
operator int () const
{
return m_Int;
}
};
#define LIST_THIS_CHECK(lst, err) \
for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) \
CHECK_COND(&(*iter) == iter->m_This, err);
bool DoTestList(std::string &error)
{
typedef SourceHook::List<Hmm> ListType;
ListType lst;
CHECK_COND(lst.empty(), "Part1");
for (int i = 1; i <= 100; ++i)
lst.push_back(i);
LIST_THIS_CHECK(lst, "PartA1");
CHECK_COND(!lst.empty(), "Part2");
lst.clear();
CHECK_COND(lst.empty(), "Part3");
for (int i = 1; i <= 100; ++i)
lst.push_back(i);
CHECK_COND(lst.back() == 100, "Part4");
LIST_THIS_CHECK(lst, "PartA2");
int ver = 1;
for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter)
CHECK_COND(*iter == ver++, "Part5");
CHECK_COND(ver == 101, "Part 6");
ListType::iterator iter50 = lst.find(50);
CHECK_COND(*iter50 == 50, "Part7");
iter50 = lst.erase(iter50);
CHECK_COND(*iter50 == 51, "Part8");
CHECK_COND(*--iter50 == 49, "Part8.2");
lst.remove(80);
ver = 1;
for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter)
{
CHECK_COND(*iter == ver++, "Part9");
if (ver == 50 || ver == 80)
++ver;
}
CHECK_COND(ver == 101, "Part10");
LIST_THIS_CHECK(lst, "PartA3");
ListType lst2;
lst = lst2;
CHECK_COND(lst.empty(), "Part11");
for (int i = 1; i <= 100; ++i)
lst.push_back(i);
lst2 = lst;
CHECK_COND(lst2.size() == 100, "Part11.2");
LIST_THIS_CHECK(lst, "PartA4");
LIST_THIS_CHECK(lst2, "PartA5");
ver = 1;
for (ListType::iterator iter = lst2.begin(); iter != lst2.end(); ++iter)
CHECK_COND(*iter == ver++, "Part12");
lst.clear();
for (int i = 401; i <= 500; ++i)
lst.push_back(i);
lst = lst2;
CHECK_COND(lst2.size() == 100, "Part13");
ver = 1;
for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter)
CHECK_COND(*iter == ver++, "Part14");
LIST_THIS_CHECK(lst, "PartA6");
LIST_THIS_CHECK(lst2, "PartA7");
return true;
}
bool DoTestTinyHash(std::string &error)
{
const int mymax = 5000;
typedef SourceHook::THash<int, int> HashType;
HashType hash;
for (int i = 1; i <= mymax; ++i)
hash[i] = i + 5000;
for (int i = 1; i <= mymax; ++i)
CHECK_COND(hash[i] == i + 5000, "Part1");
// Find
int ver = 1;
for (HashType::iterator iter = hash.begin(); iter != hash.end(); ++iter)
CHECK_COND(iter->key == ver && iter->val == (ver++) + 5000, "Part2");
CHECK_COND(ver == mymax+1, "Part2.1");
HashType::iterator iter = hash.find(300);
CHECK_COND(iter != hash.end() && iter->val == 300+5000, "Part3.1");
iter = hash.find(mymax+200);
CHECK_COND(iter == hash.end(), "Part3.2");
HashType hash2;
for (int i = 1; i <= mymax; ++i)
hash2[i] = i + 5000;
return true;
}
}
bool TestList(std::string &error)
{
if (!DoTestList(error))
return false;
if (!DoTestTinyHash(error))
return false;
return true;
}