rewritten PushStringEx in Forward and Function systems

fixed PushCellByRef and PushFloatByRef in the varargs case where it wouldn't set the pushed type
fixed the BindNatives functions not setting the BOUND flag thus making the JIT not exec the natives
done the rest of tests with forwards, only left to do string varargs

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40197
This commit is contained in:
Borja Ferrer 2006-12-06 14:52:11 +00:00
parent f305cafe8c
commit f3ad0f5b67
6 changed files with 65 additions and 29 deletions

View File

@ -7,6 +7,9 @@ namespace SourceMod
{
#define SM_FUNCFLAG_COPYBACK (1<<0) /* Copy an array/reference back after call */
#define SP_STRING_UTF8 (1<<0) /* String should be UTF-8 handled */
#define SP_STRING_COPY (1<<1) /* String should be copied into the plugin */
/**
* @brief Represents what a function needs to implement in order to be callable.
*/
@ -83,14 +86,16 @@ namespace SourceMod
virtual int PushString(const char *string) =0;
/**
* @brief Pushes a string onto the current call.
* @brief Pushes a string or string buffer.
* NOTE: On Execute, the pointer passed will be modified if copy-back is enabled.
*
* @param string String to push.
* @param flags Copy-back flags.
* @param buffer Pointer to string buffer.
* @param length Length of buffer.
* @param sz_flags String flags.
* @param cp_flags Copy-back flags.
* @return Error code, if any.
*/
virtual int PushStringEx(char *string, int flags) =0;
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) =0;
/**
* @brief Cancels a function call that is being pushed but not yet executed.

View File

@ -112,15 +112,15 @@ int CFunction::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr
int CFunction::PushString(const char *string)
{
return _PushString(string, 0);
return _PushString(string, SP_STRING_COPY, 0, strlen(string)+1);
}
int CFunction::PushStringEx(char *string, int flags)
int CFunction::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(string, flags);
return _PushString(buffer, sz_flags, cp_flags, length);
}
int CFunction::_PushString(const char *string, int flags)
int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
@ -129,8 +129,7 @@ int CFunction::_PushString(const char *string, int flags)
IPluginContext *base = m_pPlugin->m_ctx_current.base;
ParamInfo *info = &m_info[m_curparam];
size_t len = strlen(string);
size_t cells = (len + sizeof(cell_t)) / sizeof(cell_t);
size_t cells = (len + sizeof(cell_t) - 1) / sizeof(cell_t);
int err;
if ((err=base->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
@ -142,12 +141,26 @@ int CFunction::_PushString(const char *string, int flags)
m_params[m_curparam] = info->local_addr;
m_curparam++; /* Prevent a leak */
if ((err=base->StringToLocalUTF8(info->local_addr, len+1, string, NULL)) != SP_ERROR_NONE)
if (!(sz_flags & SP_STRING_COPY))
{
goto skip_localtostr;
}
if (sz_flags & SP_STRING_UTF8)
{
if ((err=base->StringToLocalUTF8(info->local_addr, len, string, NULL)) != SP_ERROR_NONE)
{
return SetError(err);
}
} else {
if ((err=base->StringToLocal(info->local_addr, len, string)) != SP_ERROR_NONE)
{
return SetError(err);
}
}
info->flags = flags;
skip_localtostr:
info->flags = cp_flags;
info->orig_addr = (cell_t *)string;
info->size = cells;

View File

@ -27,7 +27,7 @@ public:
virtual int PushFloatByRef(float *number, int flags);
virtual int PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int copyback);
virtual int PushString(const char *string);
virtual int PushStringEx(char *string, int flags);
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
virtual cell_t *GetAddressOfPushedParam(unsigned int param);
virtual int Execute(cell_t *result);
virtual void Cancel();
@ -36,7 +36,7 @@ public:
public:
void Set(funcid_t funcid, CPlugin *plugin);
private:
int _PushString(const char *string, int flags);
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
inline int SetError(int err)
{
m_errorstate = err;

View File

@ -20,12 +20,12 @@ CForwardManager g_Forwards;
* X Push strings (copyback tested = yes)
* VARARG FUNCTIONS:
* - Pushing no varargs
* - Push vararg cells (copyback should be verified to not happen = ??)
* - Push vararg cells byref (copyback tested = ??)
* - Push vararg floats (copyback should be verified to not happen = ??)
* - Push vararg floats byref (copyback tested = ??)
* - Push vararg arrays (copyback tested = ??)
* - Push vararg strings (copyback tested = ??)
* X Push vararg cells (copyback should be verified to not happen = didnt happen)
* X Push vararg cells byref (copyback tested = yes)
* X Push vararg floats (copyback should be verified to not happen = didnt happen)
* X Push vararg floats byref (copyback tested = yes)
* X Push vararg arrays (copyback tested = yes)
* X Push vararg strings (copyback tested = :TODO:)
*/
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, ...)
@ -229,7 +229,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
*/
if (type == Param_String)
{
func->PushStringEx((char *)param->byref.orig_addr, param->byref.flags);
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) {
func->PushCellByRef(&param->val, 0);
} else {
@ -365,8 +365,10 @@ int CForward::PushCellByRef(cell_t *cell, int flags)
{
if (m_curparam < m_numparams)
{
if (m_types[m_curparam] != Param_CellByRef && m_types[m_curparam] != Param_Any)
if (m_types[m_curparam] == Param_Any)
{
m_params[m_curparam].pushedas = Param_CellByRef;
} else if (m_types[m_curparam] != Param_CellByRef) {
return SetError(SP_ERROR_PARAM);
}
} else {
@ -374,6 +376,7 @@ int CForward::PushCellByRef(cell_t *cell, int flags)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_params[m_curparam].pushedas = Param_CellByRef;
}
_Int_PushArray(cell, 1, flags);
@ -386,8 +389,10 @@ int CForward::PushFloatByRef(float *num, int flags)
{
if (m_curparam < m_numparams)
{
if (m_types[m_curparam] != Param_FloatByRef && m_types[m_curparam] != Param_Any)
if (m_types[m_curparam] == Param_Any)
{
m_params[m_curparam].pushedas = Param_FloatByRef;
} else if (m_types[m_curparam] != Param_FloatByRef) {
return SetError(SP_ERROR_PARAM);
}
} else {
@ -395,6 +400,7 @@ int CForward::PushFloatByRef(float *num, int flags)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_params[m_curparam].pushedas = Param_FloatByRef;
}
_Int_PushArray((cell_t *)num, 1, flags);
@ -446,6 +452,14 @@ int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr,
return SP_ERROR_NONE;
}
void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
{
m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
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;
}
int CForward::PushString(const char *string)
{
if (m_curparam < m_numparams)
@ -464,13 +478,13 @@ int CForward::PushString(const char *string)
m_params[m_curparam].pushedas = Param_String;
}
_Int_PushArray((cell_t *)string, 0, 0);
_Int_PushString((cell_t *)string, strlen(string)+1, SP_STRING_COPY, 0);
m_curparam++;
return SP_ERROR_NONE;
}
int CForward::PushStringEx(char *string, int flags)
int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
if (m_curparam < m_numparams)
{
@ -488,7 +502,7 @@ int CForward::PushStringEx(char *string, int flags)
m_params[m_curparam].pushedas = Param_String;
}
_Int_PushArray((cell_t *)string, 0, flags);
_Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
m_curparam++;
return SP_ERROR_NONE;

View File

@ -19,6 +19,7 @@ struct ByrefInfo
unsigned int cells;
cell_t *orig_addr;
int flags;
int sz_flags;
};
struct FwdParamInfo
@ -37,7 +38,7 @@ public: //ICallable
virtual int PushFloatByRef(float *number, int flags);
virtual int PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags);
virtual int PushString(const char *string);
virtual int PushStringEx(char *string, int flags);
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
virtual void Cancel();
public: //IForward
virtual const char *GetForwardName();
@ -57,6 +58,7 @@ public:
va_list ap);
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;

View File

@ -374,6 +374,7 @@ int BaseContext::BindNative(sp_nativeinfo_t *native)
}
ctx->natives[index].pfn = native->func;
ctx->natives[index].status = SP_NATIVE_BOUND;
return SP_ERROR_NONE;
}
@ -389,6 +390,7 @@ int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
if (ctx->natives[i].status == SP_NATIVE_UNBOUND)
{
ctx->natives[i].pfn = native;
ctx->natives[i].status = SP_NATIVE_BOUND;
}
}