Values by reference in forwards

This commit is contained in:
Karol Szuster
2016-04-05 18:51:18 +02:00
parent 21c4886f90
commit 53f9144fc3
7 changed files with 222 additions and 15 deletions

View File

@ -59,7 +59,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
if (pDebugger)
pDebugger->BeginExec();
// handle strings & arrays
// handle strings & arrays & values by reference
int i;
for (i = 0; i < m_NumParams; ++i)
@ -70,7 +70,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
cell *tmp;
if (!str)
str = "";
amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp);
amx_Allot(amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp);
amx_SetStringOld(tmp, str, 0, 0);
physAddrs[i] = tmp;
}
@ -89,7 +89,24 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
*tmp++ = (static_cast<cell>(*data++)) & 0xFF;
}
} else {
}
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
cell *tmp;
amx_Allot(amx, 1, &realParams[i], &tmp);
physAddrs[i] = tmp;
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
}
else
{
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
}
}
else
{
realParams[i] = params[i];
}
}
@ -127,18 +144,18 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
if (pDebugger)
pDebugger->EndExec();
// cleanup strings & arrays
// cleanup strings & arrays & values by reference
for (i = 0; i < m_NumParams; ++i)
{
if (m_ParamTypes[i] == FP_STRING)
{
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
amx_Release(amx, realParams[i]);
}
else if (m_ParamTypes[i] == FP_STRINGEX)
{
// copy back
amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
amx_Release(amx, realParams[i]);
}
else if (m_ParamTypes[i] == FP_ARRAY)
{
@ -156,7 +173,21 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
*data++ = static_cast<char>(*tmp++ & 0xFF);
}
}
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
amx_Release(amx, realParams[i]);
}
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
//copy back
cell *tmp = physAddrs[i];
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
}
else
{
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
}
amx_Release(amx, realParams[i]);
}
}
@ -236,7 +267,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
if (pDebugger)
pDebugger->BeginExec();
// handle strings & arrays
// handle strings & arrays & values by reference
int i;
for (i = 0; i < m_NumParams; ++i)
@ -266,7 +297,24 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
*tmp++ = (static_cast<cell>(*data++)) & 0xFF;
}
} else {
}
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
cell *tmp;
amx_Allot(m_Amx, 1, &realParams[i], &tmp);
physAddrs[i] = tmp;
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
}
else
{
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
}
}
else
{
realParams[i] = params[i];
}
}
@ -300,7 +348,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
m_Amx->error = AMX_ERR_NONE;
// cleanup strings & arrays
// cleanup strings & arrays & values by reference
for (i = 0; i < m_NumParams; ++i)
{
if (m_ParamTypes[i] == FP_STRING)
@ -331,6 +379,20 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
}
amx_Release(m_Amx, realParams[i]);
}
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
//copy back
cell *tmp = physAddrs[i];
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
}
else
{
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
}
amx_Release(m_Amx, realParams[i]);
}
}
m_InExec = false;
@ -683,13 +745,26 @@ cell executeForwards(int id, ...)
va_list argptr;
va_start(argptr, id);
ForwardParam param_type;
for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i)
{
if (g_forwards.getParamType(id, i) == FP_FLOAT)
param_type = g_forwards.getParamType(id, i);
if (param_type == FP_FLOAT)
{
REAL tmp = (REAL)va_arg(argptr, double); // floats get converted to doubles
params[i] = *(cell*)&tmp;
params[i] = amx_ftoc(tmp);
}
else if(param_type == FP_FLOAT_BYREF)
{
REAL *tmp = reinterpret_cast<REAL *>(va_arg(argptr, double*));
params[i] = reinterpret_cast<cell>(tmp);
}
else if(param_type == FP_CELL_BYREF)
{
cell *tmp = reinterpret_cast<cell *>(va_arg(argptr, cell*));
params[i] = reinterpret_cast<cell>(tmp);
}
else
params[i] = (cell)va_arg(argptr, cell);

View File

@ -46,6 +46,8 @@ enum ForwardParam
FP_STRING, // string
FP_STRINGEX, // string; will be updated to the last function's value
FP_ARRAY, // array; use the return value of prepareArray.
FP_CELL_BYREF, // cell; pass by reference
FP_FLOAT_BYREF, // float; pass by reference
};
// for prepareArray

View File

@ -4118,9 +4118,13 @@ static cell AMX_NATIVE_CALL ExecuteForward(AMX *amx, cell *params)
LogError(amx, AMX_ERR_NATIVE, "Expected %d parameters, got %d", g_forwards.getParamsNum(id), count-2);
return 0;
}
ForwardParam param_type;
for (cell i=3; i<=count; i++)
{
if (g_forwards.getParamType(id, i-3) == FP_STRING)
param_type = g_forwards.getParamType(id, i-3);
if (param_type == FP_STRING)
{
char *tmp = get_amxstring(amx, params[i], 0, len);
cell num = len / sizeof(cell) + 1;
@ -4131,7 +4135,14 @@ static cell AMX_NATIVE_CALL ExecuteForward(AMX *amx, cell *params)
}
strcpy((char *)allots[i-3].phys_addr, tmp);
ps[i-3] = (cell)allots[i-3].phys_addr;
} else {
}
else if (param_type == FP_CELL_BYREF)
{
cell *temp = get_amxaddr(amx, params[i]);
ps[i-3] = reinterpret_cast<cell>(temp);
}
else
{
ps[i-3] = *get_amxaddr(amx, params[i]);
}
}