From 06da72658b4b0f6a9c08f7d7b6628b0aabe45e8f Mon Sep 17 00:00:00 2001 From: Pavol Marko Date: Sat, 3 Apr 2004 19:14:03 +0000 Subject: [PATCH] rewritten --- amxmodx/CForward.cpp | 238 +++++++++++++++++++++++++++++++++++++------ amxmodx/CForward.h | 138 ++++++++++++++----------- 2 files changed, 281 insertions(+), 95 deletions(-) diff --git a/amxmodx/CForward.cpp b/amxmodx/CForward.cpp index d0ce857e..78bcc421 100755 --- a/amxmodx/CForward.cpp +++ b/amxmodx/CForward.cpp @@ -32,49 +32,221 @@ #include #include #include "amxmodx.h" -#include "CForward.h" -void CForwardMngr::registerForward( CPluginMngr::CPlugin* p, int func , int type ){ - - CForward** a = &head[ type ]; - while(*a) a = &(*a)->next; - *a = new CForward( p , func ); - + +CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes) +{ + m_FuncName = name; + m_ExecType = et; + m_NumParams = numParams; + memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam)); + // find funcs + int func; + AMXForward *tmp = NULL; + for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter) + { + if (amx_FindPublic((*iter).getAMX(), name, &func) == AMX_ERR_NONE) + { + tmp = new AMXForward; + tmp->pPlugin = &(*iter); + tmp->func = func; + m_Funcs.put(tmp); + } + } } -void CForwardMngr::clearForwards( CForward** a ){ - while( *a ) { - CForward* b = (*a)->next; - delete *a; - *a = b; +int CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) +{ + cell realParams[FORWARD_MAX_PARAMS]; + cell *physAddrs[FORWARD_MAX_PARAMS]; + + const STRINGEX_MAXLENGTH = 128; + + int globRetVal = 0; + + for (CList::iterator iter = m_Funcs.begin(); iter; ++iter) + { + if ((*iter).pPlugin->isExecutable((*iter).func)) + { + // handle strings & arrays + int i; + for (i = 0; i < m_NumParams; ++i) + { + if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) + { + cell *tmp; + amx_Allot((*iter).pPlugin->getAMX(), + (m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast(params[i]))+1 : STRINGEX_MAXLENGTH, + &realParams[i], &tmp); + amx_SetString(tmp, (const char *)(params[i]), 0, 0); + physAddrs[i] = tmp; + } + else if (m_ParamTypes[i] == FP_ARRAY) + { + cell *tmp; + amx_Allot((*iter).pPlugin->getAMX(), preparedArrays[params[i]].size, + &realParams[i], &tmp); + physAddrs[i] = tmp; + if (preparedArrays[params[i]].type == Type_Cell) + { + memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); + } + else + { + char *data = (char*)preparedArrays[params[i]].ptr; + for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) + *tmp++ = (static_cast(*data++)) & 0xFF; + } + } + else + { + realParams[i] = params[i]; + } + } + // exec + cell retVal; + amx_Execv((*iter).pPlugin->getAMX(), &retVal, (*iter).func, m_NumParams, realParams); + // cleanup strings & arrays + for (i = 0; i < m_NumParams; ++i) + { + if (m_ParamTypes[i] == FP_STRING) + { + amx_Release((*iter).pPlugin->getAMX(), realParams[i]); + } + else if (m_ParamTypes[i] == FP_STRINGEX) + { + // copy back + amx_GetString(reinterpret_cast(params[i]), physAddrs[i], 0); + amx_Release((*iter).pPlugin->getAMX(), realParams[i]); + } + else if (m_ParamTypes[i] == FP_ARRAY) + { + // copy back + cell *tmp = physAddrs[i]; + if (preparedArrays[params[i]].type == Type_Cell) + { + memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); + } + else + { + char *data = (char*)preparedArrays[params[i]].ptr; + for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) + *data++ = static_cast(*tmp++ & 0xFF); + } + amx_Release((*iter).pPlugin->getAMX(), realParams[i]); + } + } + + // decide what to do (based on exectype and retval) + switch (m_ExecType) + { + case ET_IGNORE: + break; + case ET_STOP: + if (retVal > 0) + return retVal; + case ET_STOP2: + if (retVal == 1) + return 1; + else if (retVal > globRetVal) + globRetVal = retVal; + break; + case ET_CONTINUE: + if (retVal > globRetVal) + globRetVal = retVal; + break; + } + } } + return globRetVal; +} + +int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes) +{ + int retVal = m_Forwards.size(); + m_Forwards.push_back(new CForward(funcName, et, numParams, paramTypes)); + return retVal; +} + +bool CForwardMngr::isIdValid(int id) const +{ + return (id >= 0) && (static_cast(id) < m_Forwards.size()); +} + +int CForwardMngr::executeForwards(int id, cell *params) +{ + int retVal = m_Forwards[id]->execute(params, m_TmpArrays); + m_TmpArraysNum = 0; + return retVal; +} + +int CForwardMngr::getParamsNum(int id) const +{ + return m_Forwards[id]->getParamsNum(); } void CForwardMngr::clear() { - for ( int a = 0; a < FORWARD_NUM; ++a ) - clearForwards( &head[ a ] ); + for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter) + { + delete (*iter); + } + m_Forwards.clear(); + m_TmpArraysNum = 0; } -void CForwardMngr::executeForwards( int type , int num , int player ) { - - cell ret = 0; - int err; - CForward* a = head[ type ]; - - while ( a ) +int registerForward(const char *funcName, ForwardExecType et, ...) +{ + int curParam = 0; + va_list argptr; + va_start(argptr, et); + ForwardParam params[FORWARD_MAX_PARAMS]; + ForwardParam tmp; + while (true) { - if ( a->getPlugin()->isExecutable( a->getFunction() ) ) - { - - if ((err = amx_Exec(a->getPlugin()->getAMX(), &ret, a->getFunction() , num, player)) != AMX_ERR_NONE) - AMXXLOG_Log("[AMXX] Run time error %d on line %ld (plugin \"%s\")", err,a->getPlugin()->getAMX()->curline,a->getPlugin()->getName()); - - if ( ret ) - break; - - } - - a = a->next; + if (curParam == FORWARD_MAX_PARAMS) + break; + tmp = va_arg(argptr, ForwardParam); + if (tmp == FP_DONE) + break; + params[curParam] = tmp; + ++curParam; } + va_end(argptr); + return g_forwards.registerForward(funcName, et, curParam, params); +} + +int executeForwards(int id, ...) +{ + if (!g_forwards.isIdValid(id)) + return -1; + + cell params[FORWARD_MAX_PARAMS]; + int paramsNum = g_forwards.getParamsNum(id); + va_list argptr; + va_start(argptr, id); + for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i) + { + params[i] = va_arg(argptr, cell); + } + va_end(argptr); + return g_forwards.executeForwards(id, params); +} + +cell CForwardMngr::prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type) +{ + m_TmpArrays[m_TmpArraysNum].ptr = ptr; + m_TmpArrays[m_TmpArraysNum].size = size; + m_TmpArrays[m_TmpArraysNum].type = type; + return m_TmpArraysNum++; +} + +cell prepareCellArray(cell *ptr, unsigned int size) +{ + return g_forwards.prepareArray((void*)ptr, size, Type_Cell); +} + +cell prepareCharArray(char *ptr, unsigned int size) +{ + return g_forwards.prepareArray((void*)ptr, size, Type_Char); } \ No newline at end of file diff --git a/amxmodx/CForward.h b/amxmodx/CForward.h index 7831e153..fc78fa3d 100755 --- a/amxmodx/CForward.h +++ b/amxmodx/CForward.h @@ -36,80 +36,94 @@ // class CmdMngr // ***************************************************** -#define FORWARD_NUM 12 +const int FORWARD_MAX_PARAMS = 16; -enum { - FF_ClientCommand, - FF_ClientConnect, - FF_ClientDisconnect, - FF_ClientInfoChanged, - FF_ClientPutInServer, - FF_PluginInit, - FF_PluginCfg, - FF_PluginPrecache, - FF_PluginLog, - FF_PluginEnd, - FF_InconsistentFile, - FF_ClientAuthorized, +enum ForwardExecType +{ + ET_IGNORE = 0, // Ignore return vaue + ET_STOP, // Stop on PLUGIN_HANDLED + ET_STOP2, // Stop on PLUGIN_HANDLED, continue on other values, return biggest return value + ET_CONTINUE, // Continue; return biggest return value }; -class CForwardMngr +enum ForwardParam { -public: - - class iterator; + FP_DONE = -1, // specify this as the last argument + // only tells the function that there are no more arguments + FP_CELL, // normal cell + FP_FLOAT, // float; used as normal cell though + FP_STRING, // string + FP_STRINGEX, // string; will be updated to the last function's value + FP_ARRAY, // array; use the return value of prepareArray. +}; - class CForward +enum ForwardArrayElemType +{ + Type_Cell = 0, + Type_Char +}; + +struct ForwardPreparedArray +{ + + void *ptr; + ForwardArrayElemType type; + unsigned int size; +}; + +class CForward +{ + const char *m_FuncName; + ForwardExecType m_ExecType; + int m_NumParams; + struct AMXForward { - - friend class iterator; - friend class CForwardMngr; - - CPluginMngr::CPlugin* plugin; - int function; - CForward* next; - CForward( CPluginMngr::CPlugin* p, int func ) : plugin(p) , function(func) {next=0;} - - public: - inline CPluginMngr::CPlugin* getPlugin() { return plugin; } - inline int getFunction() { return function; } - - - + CPluginMngr::CPlugin *pPlugin; + int func; }; - - - -private: - CForward *head[ FORWARD_NUM ]; - void clearForwards( CForward** a ); - + typedef CList AMXForwardList; + AMXForwardList m_Funcs; + ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS]; public: - CForwardMngr() {memset( head, 0, sizeof(head));} - ~CForwardMngr() { clear(); } + CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam * paramTypes); + CForward() + { } // leaves everything unitialized + int execute(cell *params, ForwardPreparedArray *preparedArrays); + int getParamsNum() const + { + return m_NumParams; + } +}; + +class CForwardMngr +{ + typedef CVector ForwardVec; + ForwardVec m_Forwards; + ForwardPreparedArray m_TmpArrays[FORWARD_MAX_PARAMS]; // used by prepareArray + int m_TmpArraysNum; +public: + + CForwardMngr() + { m_TmpArraysNum = 0; } + ~CForwardMngr() + { } // Interface - - void registerForward( CPluginMngr::CPlugin* p, int func , int type ); - void executeForwards( int type , int num = 0, int player = 0 ); - void clear(); - - - class iterator { - CForward *a; - public: - iterator(CForward*aa) : a(aa) {} - iterator& operator++() { a = a->next; return *this; } - bool operator==(const iterator& b) const { return a == b.a; } - bool operator!=(const iterator& b) const { return !operator==(b); } - operator bool () const { return a ? true : false; } - CForward& operator*() { return *a; } - }; - inline iterator begin( int type ) const { return iterator(head[(int)type]); } - inline iterator end() const { return iterator(0); } - inline bool forwardsExist( int type ) {return head[(int)type]?true:false;} + int registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam *paramTypes); + int executeForwards(int id, cell *params); + void clear(); // delete all forwards + bool isIdValid(int id) const; + int getParamsNum(int id) const; + cell prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type); }; +// register forward +int registerForward(const char *funcName, ForwardExecType et, ...); +// execute forwards +int executeForwards(int id, ...); +// prepare array +cell prepareCellArray(cell *ptr, unsigned int size); +cell prepareCharArray(char *ptr, unsigned int size); #endif