rewrote forward API to use cached parameter pushing instead of immediate pushing
removed copy back cruft since it's no longer needed
removed PushCells() from API requirements, not needed
adjusted documentation and added TODO list to ForwardSys.cpp
various internal improvements
8 void CFunction::Set(funcid_t funcid, CPlugin *plugin)
13 m_errorstate = SP_ERROR_NONE;
16 int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
18 IPluginContext *ctx = m_pPlugin->m_ctx_current.base;
22 ctx->PushCell(params[num_params]);
25 return ctx->Execute(m_funcid, result);
28 IPlugin *CFunction::GetParentPlugin()
33 CFunction::CFunction(funcid_t funcid, CPlugin *plugin) :
34 m_funcid(funcid), m_pPlugin(plugin), m_curparam(0),
35 m_errorstate(SP_ERROR_NONE)
39 int CFunction::PushCell(cell_t cell)
41 if (m_curparam >= SP_MAX_EXEC_PARAMS)
43 return SetError(SP_ERROR_PARAMS_MAX);
46 m_info[m_curparam].marked = false;
47 m_params[m_curparam] = cell;
53 int CFunction::PushCellByRef(cell_t *cell, int flags)
55 if (m_curparam >= SP_MAX_EXEC_PARAMS)
57 return SetError(SP_ERROR_PARAMS_MAX);
60 return PushArray(cell, 1, NULL, flags);
63 int CFunction::PushFloat(float number)
65 cell_t val = *(cell_t *)&number;
70 int CFunction::PushFloatByRef(float *number, int flags)
72 return PushCellByRef((cell_t *)number, flags);
75 int CFunction::PushCells(cell_t array[], unsigned int numcells, bool each)
79 return PushArray(array, numcells, NULL, 0);
82 for (unsigned int i=0; i<numcells; i++)
84 if ((err=PushCell(array[i])) != SP_ERROR_NONE)
93 int CFunction::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int copyback)
95 if (m_curparam >= SP_MAX_EXEC_PARAMS)
97 return SetError(SP_ERROR_PARAMS_MAX);
100 IPluginContext *ctx = m_pPlugin->m_ctx_current.base;
101 ParamInfo *info = &m_info[m_curparam];
104 if ((err=ctx->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
106 return SetError(err);
109 info->flags = inarray ? copyback : 0;
112 m_params[m_curparam] = info->local_addr;
117 memcpy(info->phys_addr, inarray, sizeof(cell_t) * cells);
118 info->orig_addr = inarray;
120 info->orig_addr = info->phys_addr;
125 *phys_addr = info->phys_addr;
131 int CFunction::PushString(const char *string)
133 return _PushString(string, 0);
136 int CFunction::PushStringEx(char *string, int flags)
138 return _PushString(string, flags);
141 int CFunction::_PushString(const char *string, int flags)
143 if (m_curparam >= SP_MAX_EXEC_PARAMS)
145 return SetError(SP_ERROR_PARAMS_MAX);
148 IPluginContext *base = m_pPlugin->m_ctx_current.base;
149 ParamInfo *info = &m_info[m_curparam];
150 size_t len = strlen(string);
151 size_t cells = (len + sizeof(cell_t) - 1) / sizeof(cell_t);
154 if ((err=base->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
156 return SetError(err);
160 m_params[m_curparam] = info->local_addr;
161 m_curparam++; /* Prevent a leak */
163 if ((err=base->StringToLocalUTF8(info->local_addr, len, string, NULL)) != SP_ERROR_NONE)
165 return SetError(err);
169 info->orig_addr = (cell_t *)string;
172 return SP_ERROR_NONE;
175 void CFunction::Cancel()
182 IPluginContext *base = m_pPlugin->m_ctx_current.base;
186 if (m_info[m_curparam].marked)
188 base->HeapRelease(m_info[m_curparam].local_addr);
189 m_info[m_curparam].marked = false;
193 m_errorstate = SP_ERROR_NONE;
196 int CFunction::Execute(cell_t *result)
199 if (m_errorstate != SP_ERROR_NONE)
206 //This is for re-entrancy!
207 cell_t temp_params[SP_MAX_EXEC_PARAMS];
208 ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
209 unsigned int numparams = m_curparam;
210 bool docopies = true;
214 //Save the info locally, then reset it for re-entrant calls.
215 memcpy(temp_params, m_params, numparams * sizeof(cell_t));
216 memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
220 if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
225 IPluginContext *base = m_pPlugin->m_ctx_current.base;
229 if (!temp_info[numparams].marked)
233 if (docopies && temp_info[numparams].flags)
235 if (temp_info[numparams].orig_addr)
237 if (temp_info[numparams].size == 1)
239 *temp_info[numparams].orig_addr = *temp_info[numparams].phys_addr;
241 memcpy(temp_info[numparams].orig_addr,
242 temp_info[numparams].phys_addr,
243 temp_info[numparams].size * sizeof(cell_t));
247 base->HeapPop(temp_info[numparams].local_addr);
248 temp_info[numparams].marked = false;
254 cell_t *CFunction::GetAddressOfPushedParam(unsigned int param)
256 if (m_errorstate != SP_ERROR_NONE
257 || param >= m_curparam
258 || !m_info[param].marked)
263 return m_info[param].phys_addr;