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:
parent
f305cafe8c
commit
f3ad0f5b67
@ -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.
|
||||
|
@ -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))
|
||||
{
|
||||
return SetError(err);
|
||||
goto skip_localtostr;
|
||||
}
|
||||
|
||||
info->flags = flags;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
skip_localtostr:
|
||||
info->flags = cp_flags;
|
||||
info->orig_addr = (cell_t *)string;
|
||||
info->size = cells;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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, ...)
|
||||
@ -227,9 +227,9 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
/* If we're byref or we're vararg, we always push everything by ref.
|
||||
* Even if they're byval, we must push them byref.
|
||||
*/
|
||||
if (type == Param_String)
|
||||
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(¶m->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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user