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