diff -r da768ad428cf -r de7d1cd00703 core/logic/ForwardSys.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/logic/ForwardSys.h Wed Oct 09 08:43:08 2013 -0400 @@ -0,0 +1,189 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_ +#define _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_ + +#include +#include +#include "common_logic.h" +#include +#include +#include "ISourceMod.h" + +using namespace SourceHook; + +typedef List::iterator FuncIter; + +/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */ +#define FORWARDS_NAME_MAX 64 + +class FuncIteratorGuard +{ + bool triggered; + FuncIteratorGuard **pprev; + FuncIter *iter; + FuncIteratorGuard *next; +public: + FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter) + : triggered(false), pprev(pprev), iter(iter), next(*pprev) + { + *pprev = this; + } + + ~FuncIteratorGuard() + { + *pprev = next; + } + + inline bool Triggered() + { + bool t = triggered; + triggered = false; + return t; + } + + /** + * This should not read from |this| before the NULL check, because FwdSys + * can call (NULL)->FixIteratorChain(). + */ + void FixIteratorChain(FuncIter &other) + { + FuncIteratorGuard *guard = this; + while (guard != NULL) + { + if (*guard->iter == other) + { + *(guard->iter) = ++(*(guard->iter)); + guard->triggered = true; + } + guard = guard->next; + } + } +}; + +class CForward : public IChangeableForward +{ +public: //ICallable + virtual int PushCell(cell_t cell); + virtual int PushCellByRef(cell_t *cell, int flags); + virtual int PushFloat(float number); + virtual int PushFloatByRef(float *number, int flags); + virtual int PushArray(cell_t *inarray, unsigned int cells, int flags); + virtual int PushString(const char *string); + virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags); + virtual void Cancel(); +public: //IForward + virtual const char *GetForwardName(); + virtual unsigned int GetFunctionCount(); + virtual ExecType GetExecType(); + virtual int Execute(cell_t *result, IForwardFilter *filter); +public: //IChangeableForward + virtual bool RemoveFunction(IPluginFunction *func); + virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin); + virtual bool AddFunction(IPluginFunction *func); + virtual bool AddFunction(IPluginContext *ctx, funcid_t index); + virtual bool RemoveFunction(IPluginContext *ctx, funcid_t index); +public: + static CForward *CreateForward(const char *name, + ExecType et, + unsigned int num_params, + const ParamType *types, + va_list ap); + bool IsFunctionRegistered(IPluginFunction *func); +private: + void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags); + void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags); + inline int SetError(int err) + { + m_errstate = err; + return err; + } +protected: + /* :TODO: I want a caching list type here. + * Destroying these things and using new/delete for their members feels bad. + */ + mutable List m_functions; + mutable List m_paused; + FuncIteratorGuard *m_IterGuard; + + /* Type and name information */ + FwdParamInfo m_params[SP_MAX_EXEC_PARAMS]; + ParamType m_types[SP_MAX_EXEC_PARAMS]; + char m_name[FORWARDS_NAME_MAX+1]; + unsigned int m_numparams; + unsigned int m_varargs; + ExecType m_ExecType; + + /* State information */ + unsigned int m_curparam; + int m_errstate; +}; + +class CForwardManager : + public IForwardManager, + public IPluginsListener, + public SMGlobalClass +{ + friend class CForward; +public: + ~CForwardManager(); +public: //IForwardManager + IForward *CreateForward(const char *name, + ExecType et, + unsigned int num_params, + const ParamType *types, + ...); + IChangeableForward *CreateForwardEx(const char *name, + ExecType et, + int num_params, + const ParamType *types, + ...); + IForward *FindForward(const char *name, IChangeableForward **ifchng); + void ReleaseForward(IForward *forward); +public: //IPluginsListener + void OnPluginLoaded(IPlugin *plugin); + void OnPluginUnloaded(IPlugin *plugin); + void OnPluginPauseChange(IPlugin *plugin, bool paused); +public: //SMGlobalClass + void OnSourceModAllInitialized(); +protected: + CForward *ForwardMake(); + void ForwardFree(CForward *fwd); +private: + CStack m_FreeForwards; + List m_managed; + List m_unmanaged; +}; + +extern CForwardManager g_Forwards; + +#endif //_INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_