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:
Peace-Maker
2017-05-04 22:56:31 -06:00
parent b67da15b5b
commit de42dfc783
5 changed files with 214 additions and 3 deletions
+90 -2
View File
@@ -273,7 +273,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
*/
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)
{
@@ -281,7 +300,26 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
}
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);
}
}
@@ -400,6 +438,7 @@ int CForward::PushCell(cell_t cell)
m_params[m_curparam].pushedas = Param_Cell;
}
m_params[m_curparam].isnull = false;
m_params[m_curparam++].val = cell;
return SP_ERROR_NONE;
@@ -423,6 +462,7 @@ int CForward::PushFloat(float number)
m_params[m_curparam].pushedas = Param_Float;
}
m_params[m_curparam].isnull = false;
m_params[m_curparam++].val = *(cell_t *)&number;
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.flags = flags;
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)
@@ -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.orig_addr = inarray;
m_params[m_curparam].byref.sz_flags = sz_flags;
m_params[m_curparam].isnull = false;
}
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;
}
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()
{
if (!m_curparam)
+2
View File
@@ -55,6 +55,8 @@ public: //IForward
virtual unsigned int GetFunctionCount();
virtual ExecType GetExecType();
virtual int Execute(cell_t *result, IForwardFilter *filter);
virtual int PushNullString();
virtual int PushNullVector();
public: //IChangeableForward
virtual bool RemoveFunction(IPluginFunction *func);
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin);
+84
View File
@@ -552,6 +552,88 @@ static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params
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)
{
int err = SP_ERROR_NOT_RUNNABLE;
@@ -668,6 +750,8 @@ REGISTER_NATIVES(functionNatives)
{"Call_PushArrayEx", sm_CallPushArrayEx},
{"Call_PushString", sm_CallPushString},
{"Call_PushStringEx", sm_CallPushStringEx},
{"Call_PushNullVector", sm_CallPushNullVector},
{"Call_PushNullString", sm_CallPushNullString},
{"Call_Finish", sm_CallFinish},
{"Call_Cancel", sm_CallCancel},
{"RequestFrame", sm_AddFrameAction},