Add Call_PushNullVector and Call_PushNullString
Be able to push NULL_[VECTOR|STRING] to a forward or direct function call. The callee can check the parameter using the IsNullVector/IsNullString natives.
This commit is contained in:
parent
3de269946c
commit
41a9889cdd
@ -273,7 +273,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
*/
|
*/
|
||||||
if (type == Param_String)
|
if (type == Param_String)
|
||||||
{
|
{
|
||||||
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
// If NULL_STRING was pushed, push the reference to the pubvar of the callee instead.
|
||||||
|
if (param->isnull)
|
||||||
|
{
|
||||||
|
IPluginRuntime *runtime = func->GetParentRuntime();
|
||||||
|
uint32_t null_string_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
cell_t null_string;
|
||||||
|
err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = func->PushCell(null_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == Param_Float || type == Param_Cell)
|
else if (type == Param_Float || type == Param_Cell)
|
||||||
{
|
{
|
||||||
@ -281,7 +300,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
// If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead.
|
||||||
|
if (param->isnull && type == Param_Array)
|
||||||
|
{
|
||||||
|
IPluginRuntime *runtime = func->GetParentRuntime();
|
||||||
|
uint32_t null_vector_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
cell_t null_vector;
|
||||||
|
err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = func->PushCell(null_vector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
||||||
|
}
|
||||||
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,6 +438,7 @@ int CForward::PushCell(cell_t cell)
|
|||||||
m_params[m_curparam].pushedas = Param_Cell;
|
m_params[m_curparam].pushedas = Param_Cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
m_params[m_curparam++].val = cell;
|
m_params[m_curparam++].val = cell;
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
@ -423,6 +462,7 @@ int CForward::PushFloat(float number)
|
|||||||
m_params[m_curparam].pushedas = Param_Float;
|
m_params[m_curparam].pushedas = Param_Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
m_params[m_curparam++].val = *(cell_t *)&number;
|
m_params[m_curparam++].val = *(cell_t *)&number;
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
@ -481,6 +521,7 @@ void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
|
|||||||
m_params[m_curparam].byref.cells = cells;
|
m_params[m_curparam].byref.cells = cells;
|
||||||
m_params[m_curparam].byref.flags = flags;
|
m_params[m_curparam].byref.flags = flags;
|
||||||
m_params[m_curparam].byref.orig_addr = inarray;
|
m_params[m_curparam].byref.orig_addr = inarray;
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
|
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
|
||||||
@ -520,6 +561,7 @@ void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags
|
|||||||
m_params[m_curparam].byref.flags = cp_flags;
|
m_params[m_curparam].byref.flags = cp_flags;
|
||||||
m_params[m_curparam].byref.orig_addr = inarray;
|
m_params[m_curparam].byref.orig_addr = inarray;
|
||||||
m_params[m_curparam].byref.sz_flags = sz_flags;
|
m_params[m_curparam].byref.sz_flags = sz_flags;
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CForward::PushString(const char *string)
|
int CForward::PushString(const char *string)
|
||||||
@ -570,6 +612,52 @@ int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_fla
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CForward::PushNullString()
|
||||||
|
{
|
||||||
|
if (m_curparam < m_numparams)
|
||||||
|
{
|
||||||
|
if (m_types[m_curparam] == Param_Any)
|
||||||
|
{
|
||||||
|
m_params[m_curparam].pushedas = Param_String;
|
||||||
|
} else if (m_types[m_curparam] != Param_String) {
|
||||||
|
return SetError(SP_ERROR_PARAM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||||
|
{
|
||||||
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
|
}
|
||||||
|
m_params[m_curparam].pushedas = Param_String;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam++].isnull = true;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CForward::PushNullVector()
|
||||||
|
{
|
||||||
|
if (m_curparam < m_numparams)
|
||||||
|
{
|
||||||
|
if (m_types[m_curparam] == Param_Any)
|
||||||
|
{
|
||||||
|
m_params[m_curparam].pushedas = Param_Array;
|
||||||
|
} else if (m_types[m_curparam] != Param_Array) {
|
||||||
|
return SetError(SP_ERROR_PARAM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||||
|
{
|
||||||
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
|
}
|
||||||
|
m_params[m_curparam].pushedas = Param_Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam++].isnull = true;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void CForward::Cancel()
|
void CForward::Cancel()
|
||||||
{
|
{
|
||||||
if (!m_curparam)
|
if (!m_curparam)
|
||||||
|
@ -55,6 +55,8 @@ public: //IForward
|
|||||||
virtual unsigned int GetFunctionCount();
|
virtual unsigned int GetFunctionCount();
|
||||||
virtual ExecType GetExecType();
|
virtual ExecType GetExecType();
|
||||||
virtual int Execute(cell_t *result, IForwardFilter *filter);
|
virtual int Execute(cell_t *result, IForwardFilter *filter);
|
||||||
|
virtual int PushNullString();
|
||||||
|
virtual int PushNullVector();
|
||||||
public: //IChangeableForward
|
public: //IChangeableForward
|
||||||
virtual bool RemoveFunction(IPluginFunction *func);
|
virtual bool RemoveFunction(IPluginFunction *func);
|
||||||
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin);
|
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin);
|
||||||
|
@ -552,6 +552,88 @@ static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t sm_CallPushNullVector(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
int err = SP_ERROR_NOT_FOUND;
|
||||||
|
|
||||||
|
if (!s_CallStarted)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_pFunction)
|
||||||
|
{
|
||||||
|
// Find the NULL_VECTOR pubvar in the target plugin and push the local address.
|
||||||
|
IPluginRuntime *runtime = s_pFunction->GetParentRuntime();
|
||||||
|
uint32_t null_vector_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeErrorEx(err, "Target plugin has no NULL_VECTOR.");
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t null_vector;
|
||||||
|
err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = s_pCallable->PushCell(null_vector);
|
||||||
|
}
|
||||||
|
else if (s_pForward)
|
||||||
|
{
|
||||||
|
err = s_pForward->PushNullVector();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
s_pCallable->Cancel();
|
||||||
|
ResetCall();
|
||||||
|
return pContext->ThrowNativeErrorEx(err, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t sm_CallPushNullString(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
int err = SP_ERROR_NOT_FOUND;
|
||||||
|
|
||||||
|
if (!s_CallStarted)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_pFunction)
|
||||||
|
{
|
||||||
|
// Find the NULL_STRING pubvar in the target plugin and push the local address.
|
||||||
|
IPluginRuntime *runtime = s_pFunction->GetParentRuntime();
|
||||||
|
uint32_t null_string_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeErrorEx(err, "Target plugin has no NULL_STRING.");
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t null_string;
|
||||||
|
err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = s_pCallable->PushCell(null_string);
|
||||||
|
}
|
||||||
|
else if (s_pForward)
|
||||||
|
{
|
||||||
|
err = s_pForward->PushNullString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
s_pCallable->Cancel();
|
||||||
|
ResetCall();
|
||||||
|
return pContext->ThrowNativeErrorEx(err, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
|
static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
int err = SP_ERROR_NOT_RUNNABLE;
|
int err = SP_ERROR_NOT_RUNNABLE;
|
||||||
@ -668,6 +750,8 @@ REGISTER_NATIVES(functionNatives)
|
|||||||
{"Call_PushArrayEx", sm_CallPushArrayEx},
|
{"Call_PushArrayEx", sm_CallPushArrayEx},
|
||||||
{"Call_PushString", sm_CallPushString},
|
{"Call_PushString", sm_CallPushString},
|
||||||
{"Call_PushStringEx", sm_CallPushStringEx},
|
{"Call_PushStringEx", sm_CallPushStringEx},
|
||||||
|
{"Call_PushNullVector", sm_CallPushNullVector},
|
||||||
|
{"Call_PushNullString", sm_CallPushNullString},
|
||||||
{"Call_Finish", sm_CallFinish},
|
{"Call_Finish", sm_CallFinish},
|
||||||
{"Call_Cancel", sm_CallCancel},
|
{"Call_Cancel", sm_CallCancel},
|
||||||
{"RequestFrame", sm_AddFrameAction},
|
{"RequestFrame", sm_AddFrameAction},
|
||||||
|
@ -290,6 +290,16 @@ native void Call_PushArray(const any[] value, int size);
|
|||||||
*/
|
*/
|
||||||
native void Call_PushArrayEx(any[] value, int size, int cpflags);
|
native void Call_PushArrayEx(any[] value, int size, int cpflags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the NULL_VECTOR onto the current call.
|
||||||
|
* @see IsNullVector
|
||||||
|
*
|
||||||
|
* @note Cannot be used before a call has been started.
|
||||||
|
*
|
||||||
|
* @error Called before a call has been started.
|
||||||
|
*/
|
||||||
|
native void Call_PushNullVector();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes a string onto the current call.
|
* Pushes a string onto the current call.
|
||||||
*
|
*
|
||||||
@ -317,6 +327,16 @@ native void Call_PushString(const char[] value);
|
|||||||
*/
|
*/
|
||||||
native void Call_PushStringEx(char[] value, int length, int szflags, int cpflags);
|
native void Call_PushStringEx(char[] value, int length, int szflags, int cpflags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the NULL_STRING onto the current call.
|
||||||
|
* @see IsNullString
|
||||||
|
*
|
||||||
|
* @note Cannot be used before a call has been started.
|
||||||
|
*
|
||||||
|
* @error Called before a call has been started.
|
||||||
|
*/
|
||||||
|
native void Call_PushNullString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completes a call to a function or forward's call list.
|
* Completes a call to a function or forward's call list.
|
||||||
*
|
*
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
using namespace SourcePawn;
|
using namespace SourcePawn;
|
||||||
|
|
||||||
#define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager"
|
#define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager"
|
||||||
#define SMINTERFACE_FORWARDMANAGER_VERSION 3
|
#define SMINTERFACE_FORWARDMANAGER_VERSION 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is some very important documentation at the bottom of this file.
|
* There is some very important documentation at the bottom of this file.
|
||||||
@ -118,6 +118,7 @@ namespace SourceMod
|
|||||||
cell_t val;
|
cell_t val;
|
||||||
ByrefInfo byref;
|
ByrefInfo byref;
|
||||||
ParamType pushedas;
|
ParamType pushedas;
|
||||||
|
bool isnull;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IForwardFilter
|
class IForwardFilter
|
||||||
@ -183,6 +184,22 @@ namespace SourceMod
|
|||||||
* @return Error code, if any.
|
* @return Error code, if any.
|
||||||
*/
|
*/
|
||||||
virtual int PushArray(cell_t *inarray, unsigned int cells, int flags=0) =0;
|
virtual int PushArray(cell_t *inarray, unsigned int cells, int flags=0) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes the NULL_STRING onto the current call. This will always push the
|
||||||
|
* correct reference to each function in the forward.
|
||||||
|
*
|
||||||
|
* @return Error code, if any.
|
||||||
|
*/
|
||||||
|
virtual int PushNullString() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes the NULL_VECTOR onto the current call. This will always push the
|
||||||
|
* correct reference to each function in the forward.
|
||||||
|
*
|
||||||
|
* @return Error code, if any.
|
||||||
|
*/
|
||||||
|
virtual int PushNullVector() =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user