1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/logic/ForwardSys.cpp Wed Oct 09 08:43:08 2013 -0400
1.3 @@ -0,0 +1,794 @@
1.4 +/**
1.5 + * vim: set ts=4 sw=4 tw=99 noet :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include <assert.h>
1.36 +#include <stdarg.h>
1.37 +#include <string.h>
1.38 +#include "ForwardSys.h"
1.39 +#include "DebugReporter.h"
1.40 +#include "common_logic.h"
1.41 +
1.42 +CForwardManager g_Forwards;
1.43 +
1.44 +/**
1.45 + * Genesis turns to its source, reduction occurs stepwise although the essence is all one.
1.46 + * End of line. FTL system check.
1.47 + *
1.48 + * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
1.49 + * VARARG FUNCTIONS:
1.50 + * - Pushing no varargs
1.51 + */
1.52 +
1.53 +// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
1.54 +// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
1.55 +
1.56 +CForwardManager::~CForwardManager()
1.57 +{
1.58 + CStack<CForward *>::iterator iter;
1.59 + for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
1.60 + {
1.61 + delete (*iter);
1.62 + }
1.63 + m_FreeForwards.popall();
1.64 +}
1.65 +
1.66 +void CForwardManager::OnSourceModAllInitialized()
1.67 +{
1.68 + scripts->AddPluginsListener(this);
1.69 + sharesys->AddInterface(NULL, this);
1.70 +}
1.71 +
1.72 +IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
1.73 +{
1.74 + CForward *fwd;
1.75 + va_list ap;
1.76 + va_start(ap, types);
1.77 +
1.78 + fwd = CForward::CreateForward(name, et, num_params, types, ap);
1.79 +
1.80 + va_end(ap);
1.81 +
1.82 + if (fwd)
1.83 + {
1.84 + scripts->AddFunctionsToForward(name, fwd);
1.85 +
1.86 + m_managed.push_back(fwd);
1.87 + }
1.88 +
1.89 + return fwd;
1.90 +}
1.91 +
1.92 +IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
1.93 +{
1.94 + CForward *fwd;
1.95 + va_list ap;
1.96 + va_start(ap, types);
1.97 +
1.98 + fwd = CForward::CreateForward(name, et, num_params, types, ap);
1.99 +
1.100 + va_end(ap);
1.101 +
1.102 + if (fwd)
1.103 + {
1.104 + m_unmanaged.push_back(fwd);
1.105 + }
1.106 +
1.107 + return fwd;
1.108 +}
1.109 +
1.110 +void CForwardManager::OnPluginLoaded(IPlugin *plugin)
1.111 +{
1.112 + /* Attach any globally managed forwards */
1.113 + List<CForward *>::iterator iter;
1.114 + CForward *fwd;
1.115 +
1.116 + for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
1.117 + {
1.118 + fwd = (*iter);
1.119 + IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
1.120 + if (pFunc)
1.121 + {
1.122 + fwd->AddFunction(pFunc);
1.123 + }
1.124 + }
1.125 +}
1.126 +
1.127 +void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
1.128 +{
1.129 + List<CForward *>::iterator iter;
1.130 + CForward *fwd;
1.131 +
1.132 + for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
1.133 + {
1.134 + fwd = (*iter);
1.135 + fwd->RemoveFunctionsOfPlugin(plugin);
1.136 + }
1.137 +
1.138 + for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
1.139 + {
1.140 + fwd = (*iter);
1.141 + fwd->RemoveFunctionsOfPlugin(plugin);
1.142 + }
1.143 +}
1.144 +
1.145 +IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
1.146 +{
1.147 + List<CForward *>::iterator iter;
1.148 + CForward *fwd;
1.149 +
1.150 + for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
1.151 + {
1.152 + fwd = (*iter);
1.153 + if (strcmp(fwd->GetForwardName(), name) == 0)
1.154 + {
1.155 + if (ifchng)
1.156 + {
1.157 + *ifchng = NULL;
1.158 + }
1.159 + return fwd;
1.160 + }
1.161 + }
1.162 +
1.163 + for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
1.164 + {
1.165 + fwd = (*iter);
1.166 + if (strcmp(fwd->GetForwardName(), name) == 0)
1.167 + {
1.168 + if (ifchng)
1.169 + {
1.170 + *ifchng = fwd;
1.171 + }
1.172 + return fwd;
1.173 + }
1.174 + }
1.175 +
1.176 + if (ifchng)
1.177 + {
1.178 + *ifchng = NULL;
1.179 + }
1.180 +
1.181 + return NULL;
1.182 +}
1.183 +
1.184 +void CForwardManager::ReleaseForward(IForward *forward)
1.185 +{
1.186 + ForwardFree(static_cast<CForward *>(forward));
1.187 +}
1.188 +
1.189 +void CForwardManager::ForwardFree(CForward *fwd)
1.190 +{
1.191 + if (fwd == NULL)
1.192 + {
1.193 + return;
1.194 + }
1.195 +
1.196 + m_FreeForwards.push(fwd);
1.197 + m_managed.remove(fwd);
1.198 +}
1.199 +
1.200 +CForward *CForwardManager::ForwardMake()
1.201 +{
1.202 + CForward *fwd;
1.203 + if (m_FreeForwards.empty())
1.204 + {
1.205 + fwd = new CForward;
1.206 + } else {
1.207 + fwd = m_FreeForwards.front();
1.208 + m_FreeForwards.pop();
1.209 + }
1.210 + return fwd;
1.211 +}
1.212 +
1.213 +void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
1.214 +{
1.215 + if(paused)
1.216 + return;
1.217 +
1.218 + /* Attach any globally managed forwards */
1.219 + List<CForward *>::iterator iter;
1.220 + CForward *fwd;
1.221 +
1.222 + for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
1.223 + {
1.224 + fwd = (*iter);
1.225 + IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
1.226 + // Only add functions, if they aren't registered yet!
1.227 + if (pFunc && !fwd->IsFunctionRegistered(pFunc))
1.228 + {
1.229 + fwd->AddFunction(pFunc);
1.230 + }
1.231 + }
1.232 +}
1.233 +
1.234 +/*************************************
1.235 + * ACTUAL FORWARD API IMPLEMENTATION *
1.236 + *************************************/
1.237 +
1.238 +CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
1.239 +{
1.240 + ParamType _types[SP_MAX_EXEC_PARAMS];
1.241 +
1.242 + if (num_params > SP_MAX_EXEC_PARAMS)
1.243 + {
1.244 + return NULL;
1.245 + }
1.246 +
1.247 + if (types == NULL && num_params)
1.248 + {
1.249 + for (unsigned int i=0; i<num_params; i++)
1.250 + {
1.251 + _types[i] = (ParamType)va_arg(ap, int);
1.252 + if (_types[i] == Param_VarArgs && (i != num_params - 1))
1.253 + {
1.254 + return NULL;
1.255 + }
1.256 + }
1.257 + types = _types;
1.258 + } else {
1.259 + for (unsigned int i=0; i<num_params; i++)
1.260 + {
1.261 + _types[i] = types[i];
1.262 + if (types[i] == Param_VarArgs && (i != num_params - 1))
1.263 + {
1.264 + return NULL;
1.265 + }
1.266 + }
1.267 + }
1.268 +
1.269 + /* First parameter can never be varargs */
1.270 + if (num_params && _types[0] == Param_VarArgs)
1.271 + {
1.272 + return NULL;
1.273 + }
1.274 +
1.275 + CForward *pForward = g_Forwards.ForwardMake();
1.276 + pForward->m_IterGuard = NULL;
1.277 + pForward->m_curparam = 0;
1.278 + pForward->m_ExecType = et;
1.279 + snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
1.280 +
1.281 + for (unsigned int i=0; i<num_params; i++)
1.282 + {
1.283 + pForward->m_types[i] = _types[i];
1.284 + }
1.285 +
1.286 + if (num_params && _types[num_params-1] == Param_VarArgs)
1.287 + {
1.288 + pForward->m_varargs = num_params--;
1.289 + } else {
1.290 + pForward->m_varargs = false;
1.291 + }
1.292 +
1.293 + pForward->m_numparams = num_params;
1.294 + pForward->m_errstate = SP_ERROR_NONE;
1.295 +
1.296 + pForward->m_functions.clear();
1.297 +
1.298 + return pForward;
1.299 +}
1.300 +
1.301 +int CForward::Execute(cell_t *result, IForwardFilter *filter)
1.302 +{
1.303 + if (m_errstate)
1.304 + {
1.305 + int err = m_errstate;
1.306 + Cancel();
1.307 + return err;
1.308 + }
1.309 +
1.310 + FuncIter iter = m_functions.begin();
1.311 + IPluginFunction *func;
1.312 + cell_t cur_result = 0;
1.313 + cell_t high_result = 0;
1.314 + cell_t low_result = 0;
1.315 + int err;
1.316 + unsigned int success=0;
1.317 + unsigned int num_params = m_curparam;
1.318 + FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
1.319 + FwdParamInfo *param;
1.320 + ParamType type;
1.321 +
1.322 + /* Save local, reset */
1.323 + memcpy(temp_info, m_params, sizeof(m_params));
1.324 + m_curparam = 0;
1.325 +
1.326 + FuncIteratorGuard guard(&m_IterGuard, &iter);
1.327 +
1.328 + while (iter != m_functions.end())
1.329 + {
1.330 + func = (*iter);
1.331 +
1.332 + if (filter)
1.333 + filter->Preprocess(func, temp_info);
1.334 +
1.335 + for (unsigned int i=0; i<num_params; i++)
1.336 + {
1.337 + int err = SP_ERROR_PARAM;
1.338 + param = &temp_info[i];
1.339 +
1.340 + if (i >= m_numparams || m_types[i] == Param_Any)
1.341 + {
1.342 + type = param->pushedas;
1.343 + }
1.344 + else
1.345 + {
1.346 + type = m_types[i];
1.347 + }
1.348 +
1.349 + if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
1.350 + {
1.351 + /* If we're byref or we're vararg, we always push everything by ref.
1.352 + * Even if they're byval, we must push them byref.
1.353 + */
1.354 + if (type == Param_String)
1.355 + {
1.356 + err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
1.357 + }
1.358 + else if (type == Param_Float || type == Param_Cell)
1.359 + {
1.360 + err = func->PushCellByRef(¶m->val);
1.361 + }
1.362 + else
1.363 + {
1.364 + err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
1.365 + assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
1.366 + }
1.367 + }
1.368 + else
1.369 + {
1.370 + /* If we're not byref or not vararg, our job is a bit easier. */
1.371 + assert(type == Param_Cell || type == Param_Float);
1.372 + err = func->PushCell(param->val);
1.373 + }
1.374 +
1.375 + if (err != SP_ERROR_NONE)
1.376 + {
1.377 + g_DbgReporter.GenerateError(func->GetParentContext(),
1.378 + func->GetFunctionID(),
1.379 + err,
1.380 + "Failed to push parameter while executing forward");
1.381 + continue;
1.382 + }
1.383 + }
1.384 +
1.385 + /* Call the function and deal with the return value. */
1.386 + if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
1.387 + {
1.388 + success++;
1.389 + switch (m_ExecType)
1.390 + {
1.391 + case ET_Event:
1.392 + {
1.393 + if (cur_result > high_result)
1.394 + {
1.395 + high_result = cur_result;
1.396 + }
1.397 + break;
1.398 + }
1.399 + case ET_Hook:
1.400 + {
1.401 + if (cur_result > high_result)
1.402 + {
1.403 + high_result = cur_result;
1.404 + if ((ResultType)high_result == Pl_Stop)
1.405 + {
1.406 + goto done;
1.407 + }
1.408 + }
1.409 + break;
1.410 + }
1.411 + case ET_LowEvent:
1.412 + {
1.413 + /* Check if the current result is the lowest so far (or if it's the first result) */
1.414 + if (cur_result < low_result || success == 1)
1.415 + {
1.416 + low_result = cur_result;
1.417 + }
1.418 + break;
1.419 + }
1.420 + default:
1.421 + {
1.422 + break;
1.423 + }
1.424 + }
1.425 + }
1.426 +
1.427 + if (!guard.Triggered())
1.428 + iter++;
1.429 + }
1.430 +
1.431 +done:
1.432 +
1.433 + if (success)
1.434 + {
1.435 + switch (m_ExecType)
1.436 + {
1.437 + case ET_Ignore:
1.438 + {
1.439 + cur_result = 0;
1.440 + break;
1.441 + }
1.442 + case ET_Event:
1.443 + case ET_Hook:
1.444 + {
1.445 + cur_result = high_result;
1.446 + break;
1.447 + }
1.448 + case ET_LowEvent:
1.449 + {
1.450 + cur_result = low_result;
1.451 + break;
1.452 + }
1.453 + default:
1.454 + {
1.455 + break;
1.456 + }
1.457 + }
1.458 +
1.459 + if (result)
1.460 + {
1.461 + *result = cur_result;
1.462 + }
1.463 + }
1.464 +
1.465 + return SP_ERROR_NONE;
1.466 +}
1.467 +
1.468 +int CForward::PushCell(cell_t cell)
1.469 +{
1.470 + if (m_curparam < m_numparams)
1.471 + {
1.472 + if (m_types[m_curparam] == Param_Any)
1.473 + {
1.474 + m_params[m_curparam].pushedas = Param_Cell;
1.475 + } else if (m_types[m_curparam] != Param_Cell) {
1.476 + return SetError(SP_ERROR_PARAM);
1.477 + }
1.478 + } else {
1.479 + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
1.480 + {
1.481 + return SetError(SP_ERROR_PARAMS_MAX);
1.482 + }
1.483 + m_params[m_curparam].pushedas = Param_Cell;
1.484 + }
1.485 +
1.486 + m_params[m_curparam++].val = cell;
1.487 +
1.488 + return SP_ERROR_NONE;
1.489 +}
1.490 +
1.491 +int CForward::PushFloat(float number)
1.492 +{
1.493 + if (m_curparam < m_numparams)
1.494 + {
1.495 + if (m_types[m_curparam] == Param_Any)
1.496 + {
1.497 + m_params[m_curparam].pushedas = Param_Float;
1.498 + } else if (m_types[m_curparam] != Param_Float) {
1.499 + return SetError(SP_ERROR_PARAM);
1.500 + }
1.501 + } else {
1.502 + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
1.503 + {
1.504 + return SetError(SP_ERROR_PARAMS_MAX);
1.505 + }
1.506 + m_params[m_curparam].pushedas = Param_Float;
1.507 + }
1.508 +
1.509 + m_params[m_curparam++].val = *(cell_t *)&number;
1.510 +
1.511 + return SP_ERROR_NONE;
1.512 +}
1.513 +
1.514 +int CForward::PushCellByRef(cell_t *cell, int flags)
1.515 +{
1.516 + if (m_curparam < m_numparams)
1.517 + {
1.518 + if (m_types[m_curparam] == Param_Any)
1.519 + {
1.520 + m_params[m_curparam].pushedas = Param_CellByRef;
1.521 + } else if (m_types[m_curparam] != Param_CellByRef) {
1.522 + return SetError(SP_ERROR_PARAM);
1.523 + }
1.524 + } else {
1.525 + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
1.526 + {
1.527 + return SetError(SP_ERROR_PARAMS_MAX);
1.528 + }
1.529 + m_params[m_curparam].pushedas = Param_CellByRef;
1.530 + }
1.531 +
1.532 + _Int_PushArray(cell, 1, flags);
1.533 + m_curparam++;
1.534 +
1.535 + return SP_ERROR_NONE;
1.536 +}
1.537 +
1.538 +int CForward::PushFloatByRef(float *num, int flags)
1.539 +{
1.540 + if (m_curparam < m_numparams)
1.541 + {
1.542 + if (m_types[m_curparam] == Param_Any)
1.543 + {
1.544 + m_params[m_curparam].pushedas = Param_FloatByRef;
1.545 + } else if (m_types[m_curparam] != Param_FloatByRef) {
1.546 + return SetError(SP_ERROR_PARAM);
1.547 + }
1.548 + } else {
1.549 + if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
1.550 + {
1.551 + return SetError(SP_ERROR_PARAMS_MAX);
1.552 + }
1.553 + m_params[m_curparam].pushedas = Param_FloatByRef;
1.554 + }
1.555 +
1.556 + _Int_PushArray((cell_t *)num, 1, flags);
1.557 + m_curparam++;
1.558 +
1.559 + return SP_ERROR_NONE;
1.560 +}
1.561 +
1.562 +void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
1.563 +{
1.564 + m_params[m_curparam].byref.cells = cells;
1.565 + m_params[m_curparam].byref.flags = flags;
1.566 + m_params[m_curparam].byref.orig_addr = inarray;
1.567 +}
1.568 +
1.569 +int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
1.570 +{
1.571 + /* We don't allow this here */
1.572 + if (!inarray)
1.573 + {
1.574 + return SetError(SP_ERROR_PARAM);
1.575 + }
1.576 +
1.577 + if (m_curparam < m_numparams)
1.578 + {
1.579 + if (m_types[m_curparam] == Param_Any)
1.580 + {
1.581 + m_params[m_curparam].pushedas = Param_Array;
1.582 + } else if (m_types[m_curparam] != Param_Array) {
1.583 + return SetError(SP_ERROR_PARAM);
1.584 + }
1.585 + } else {
1.586 + if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
1.587 + {
1.588 + return SetError(SP_ERROR_PARAMS_MAX);
1.589 + }
1.590 + m_params[m_curparam].pushedas = Param_Array;
1.591 + }
1.592 +
1.593 + _Int_PushArray(inarray, cells, flags);
1.594 +
1.595 + m_curparam++;
1.596 +
1.597 + return SP_ERROR_NONE;
1.598 +}
1.599 +
1.600 +void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
1.601 +{
1.602 + m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
1.603 + m_params[m_curparam].byref.flags = cp_flags;
1.604 + m_params[m_curparam].byref.orig_addr = inarray;
1.605 + m_params[m_curparam].byref.sz_flags = sz_flags;
1.606 +}
1.607 +
1.608 +int CForward::PushString(const char *string)
1.609 +{
1.610 + if (m_curparam < m_numparams)
1.611 + {
1.612 + if (m_types[m_curparam] == Param_Any)
1.613 + {
1.614 + m_params[m_curparam].pushedas = Param_String;
1.615 + } else if (m_types[m_curparam] != Param_String) {
1.616 + return SetError(SP_ERROR_PARAM);
1.617 + }
1.618 + } else {
1.619 + if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
1.620 + {
1.621 + return SetError(SP_ERROR_PARAMS_MAX);
1.622 + }
1.623 + m_params[m_curparam].pushedas = Param_String;
1.624 + }
1.625 +
1.626 + _Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
1.627 + m_curparam++;
1.628 +
1.629 + return SP_ERROR_NONE;
1.630 +}
1.631 +
1.632 +int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
1.633 +{
1.634 + if (m_curparam < m_numparams)
1.635 + {
1.636 + if (m_types[m_curparam] == Param_Any)
1.637 + {
1.638 + m_params[m_curparam].pushedas = Param_String;
1.639 + } else if (m_types[m_curparam] != Param_String) {
1.640 + return SetError(SP_ERROR_PARAM);
1.641 + }
1.642 + } else {
1.643 + if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
1.644 + {
1.645 + return SetError(SP_ERROR_PARAMS_MAX);
1.646 + }
1.647 + m_params[m_curparam].pushedas = Param_String;
1.648 + }
1.649 +
1.650 + _Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
1.651 + m_curparam++;
1.652 +
1.653 + return SP_ERROR_NONE;
1.654 +}
1.655 +
1.656 +void CForward::Cancel()
1.657 +{
1.658 + if (!m_curparam)
1.659 + {
1.660 + return;
1.661 + }
1.662 +
1.663 + m_curparam = 0;
1.664 + m_errstate = SP_ERROR_NONE;
1.665 +}
1.666 +
1.667 +bool CForward::AddFunction(IPluginContext *pContext, funcid_t index)
1.668 +{
1.669 + IPluginFunction *pFunc = pContext->GetFunctionById(index);
1.670 +
1.671 + if (!pFunc)
1.672 + {
1.673 + return false;
1.674 + }
1.675 +
1.676 + return AddFunction(pFunc);
1.677 +}
1.678 +
1.679 +bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
1.680 +{
1.681 + IPluginFunction *pFunc = pContext->GetFunctionById(index);
1.682 +
1.683 + if (!pFunc)
1.684 + {
1.685 + return false;
1.686 + }
1.687 +
1.688 + return RemoveFunction(pFunc);
1.689 +}
1.690 +
1.691 +bool CForward::RemoveFunction(IPluginFunction *func)
1.692 +{
1.693 + bool found = false;
1.694 + FuncIter iter;
1.695 + List<IPluginFunction *> *lst;
1.696 +
1.697 + if (func->IsRunnable())
1.698 + {
1.699 + lst = &m_functions;
1.700 + } else {
1.701 + lst = &m_paused;
1.702 + }
1.703 +
1.704 + for (iter=lst->begin(); iter!=lst->end(); iter++)
1.705 + {
1.706 + if ((*iter) == func)
1.707 + {
1.708 + m_IterGuard->FixIteratorChain(iter);
1.709 + found = true;
1.710 + lst->erase(iter);
1.711 + break;
1.712 + }
1.713 + }
1.714 +
1.715 + /* Cancel a call, if any */
1.716 + if (found || m_curparam)
1.717 + {
1.718 + func->Cancel();
1.719 + }
1.720 +
1.721 + return found;
1.722 +}
1.723 +
1.724 +unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
1.725 +{
1.726 + FuncIter iter;
1.727 + IPluginFunction *func;
1.728 + unsigned int removed = 0;
1.729 + IPluginContext *pContext = plugin->GetBaseContext();
1.730 + for (iter=m_functions.begin(); iter!=m_functions.end();)
1.731 + {
1.732 + func = (*iter);
1.733 + if (func->GetParentContext() == pContext)
1.734 + {
1.735 + iter = m_functions.erase(iter);
1.736 + removed++;
1.737 + } else {
1.738 + iter++;
1.739 + }
1.740 + }
1.741 +
1.742 + return removed;
1.743 +}
1.744 +
1.745 +bool CForward::AddFunction(IPluginFunction *func)
1.746 +{
1.747 + if (m_curparam)
1.748 + {
1.749 + return false;
1.750 + }
1.751 +
1.752 + if (func->IsRunnable())
1.753 + {
1.754 + m_functions.push_back(func);
1.755 + } else {
1.756 + m_paused.push_back(func);
1.757 + }
1.758 +
1.759 + return true;
1.760 +}
1.761 +
1.762 +bool CForward::IsFunctionRegistered(IPluginFunction *func)
1.763 +{
1.764 + FuncIter iter;
1.765 + List<IPluginFunction *> *lst;
1.766 +
1.767 + if (func->IsRunnable())
1.768 + {
1.769 + lst = &m_functions;
1.770 + } else {
1.771 + lst = &m_paused;
1.772 + }
1.773 +
1.774 + for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
1.775 + {
1.776 + if ((*iter) == func)
1.777 + {
1.778 + return true;
1.779 + }
1.780 + }
1.781 + return false;
1.782 +}
1.783 +
1.784 +const char *CForward::GetForwardName()
1.785 +{
1.786 + return m_name;
1.787 +}
1.788 +
1.789 +unsigned int CForward::GetFunctionCount()
1.790 +{
1.791 + return m_functions.size();
1.792 +}
1.793 +
1.794 +ExecType CForward::GetExecType()
1.795 +{
1.796 + return m_ExecType;
1.797 +}