core/systems/ForwardSys.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 12 01:06:17 2006 +0000 (2006-11-12)
changeset 180 fe406c5f2aeb
child 181 1e1570518051
permissions -rw-r--r--
Initial import of forward system
dvander@180
     1
#include <assert.h>
dvander@180
     2
#include "ForwardSys.h"
dvander@180
     3
#include "PluginSys.h"
dvander@180
     4
dvander@180
     5
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
dvander@180
     6
{
dvander@180
     7
	ParamType _types[SP_MAX_EXEC_PARAMS];
dvander@180
     8
dvander@180
     9
	if (num_params > SP_MAX_EXEC_PARAMS)
dvander@180
    10
	{
dvander@180
    11
		return NULL;
dvander@180
    12
	}
dvander@180
    13
	
dvander@180
    14
	if (types == NULL && num_params)
dvander@180
    15
	{
dvander@180
    16
		for (unsigned int i=0; i<num_params; i++)
dvander@180
    17
		{
dvander@180
    18
			_types[i] = va_arg(ap, ParamType);
dvander@180
    19
			if (_types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
    20
			{
dvander@180
    21
				return NULL;
dvander@180
    22
			}
dvander@180
    23
		}
dvander@180
    24
		types = _types;
dvander@180
    25
	} else {
dvander@180
    26
		for (unsigned int i=0; i<num_params; i++)
dvander@180
    27
		{
dvander@180
    28
			if (types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
    29
			{
dvander@180
    30
				return NULL;
dvander@180
    31
			}
dvander@180
    32
		}
dvander@180
    33
	}
dvander@180
    34
dvander@180
    35
	/* First parameter can never be varargs */
dvander@180
    36
	if (types[0] == Param_VarArgs)
dvander@180
    37
	{
dvander@180
    38
		return NULL;
dvander@180
    39
	}
dvander@180
    40
dvander@180
    41
	CForward *pForward = new CForward;
dvander@180
    42
	pForward->m_curparam = 0;
dvander@180
    43
	pForward->m_ExecType = et;
dvander@180
    44
	snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
dvander@180
    45
	
dvander@180
    46
	for (unsigned int i=0; i<num_params; i++)
dvander@180
    47
	{
dvander@180
    48
		pForward->m_types[i] = types[i];
dvander@180
    49
	}
dvander@180
    50
dvander@180
    51
	if (num_params && types[num_params-1] == Param_VarArgs)
dvander@180
    52
	{
dvander@180
    53
		pForward->m_varargs = true;
dvander@180
    54
	} else {
dvander@180
    55
		pForward->m_varargs = false;
dvander@180
    56
	}
dvander@180
    57
dvander@180
    58
	pForward->m_numparams = num_params;
dvander@180
    59
	pForward->m_errstate = SP_ERROR_NONE;
dvander@180
    60
	pForward->m_CopyBacks.numrecopy = 0;
dvander@180
    61
dvander@180
    62
	return pForward;
dvander@180
    63
}
dvander@180
    64
dvander@180
    65
bool CForward::OnCopybackArray(unsigned int param, 
dvander@180
    66
							   unsigned int cells, 
dvander@180
    67
							   cell_t *source_addr, 
dvander@180
    68
							   cell_t *orig_addr, 
dvander@180
    69
							   int flags)
dvander@180
    70
{
dvander@180
    71
	/* Check if the stack is empty, this should be an assertion */
dvander@180
    72
	if (m_NextStack.empty())
dvander@180
    73
	{
dvander@180
    74
		/* This should never happen! */
dvander@180
    75
		assert(!m_NextStack.empty());
dvander@180
    76
		return true;
dvander@180
    77
	}
dvander@180
    78
dvander@180
    79
	/* Check if we even want to copy to the next plugin */
dvander@180
    80
	if (!(flags & SMFUNC_COPYBACK_ALWAYS))
dvander@180
    81
	{
dvander@180
    82
		return true;
dvander@180
    83
	}
dvander@180
    84
dvander@180
    85
	/* Keep track of the copy back and save the info */
dvander@180
    86
	NextCallInfo &info = m_NextStack.front();
dvander@180
    87
	info.recopy[info.numrecopy++] = param;
dvander@180
    88
	info.orig_addrs[param] = orig_addr;
dvander@180
    89
	info.sizes[param] = cells;
dvander@180
    90
dvander@180
    91
	/* We don't want to override the copy. */
dvander@180
    92
	return true;
dvander@180
    93
}
dvander@180
    94
dvander@180
    95
int CForward::Execute(cell_t *result, IForwardFilter *filter)
dvander@180
    96
{
dvander@180
    97
	if (m_errstate)
dvander@180
    98
	{
dvander@180
    99
		int err = m_errstate;
dvander@180
   100
		Cancel();
dvander@180
   101
		return err;
dvander@180
   102
	}
dvander@180
   103
dvander@180
   104
	/* Reset marker */
dvander@180
   105
	m_curparam = 0;
dvander@180
   106
dvander@180
   107
	if (filter)
dvander@180
   108
	{
dvander@180
   109
		filter->OnExecuteBegin();
dvander@180
   110
	}
dvander@180
   111
dvander@180
   112
	FuncIter iter = m_functions.begin();
dvander@180
   113
	IPluginFunction *func;
dvander@180
   114
	cell_t cur_result = 0;
dvander@180
   115
	cell_t high_result = 0;
dvander@180
   116
	int err;
dvander@180
   117
	unsigned int failed=0, success=0;
dvander@180
   118
	unsigned int save_numcopy = 0;
dvander@180
   119
dvander@180
   120
	/** 
dvander@180
   121
	 * Save copyback into to start the chain, 
dvander@180
   122
	 * then reset it for re-entrancy
dvander@180
   123
	 */
dvander@180
   124
	m_NextStack.push(m_CopyBacks);
dvander@180
   125
	NextCallInfo &info = m_NextStack.front();
dvander@180
   126
	m_CopyBacks.numrecopy = 0;
dvander@180
   127
	
dvander@180
   128
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   129
	{
dvander@180
   130
		func = (*iter);
dvander@180
   131
		
dvander@180
   132
		/**
dvander@180
   133
		 * Check if we need to copy a new array back into the plugin.
dvander@180
   134
		 */
dvander@180
   135
		if (info.numrecopy)
dvander@180
   136
		{
dvander@180
   137
			/* The last plugin has a chained copyback, we must redirect it here. */
dvander@180
   138
			unsigned int param;
dvander@180
   139
			cell_t *orig_addr, *targ_addr;
dvander@180
   140
			for (unsigned int i=0; i<info.numrecopy; i++)
dvander@180
   141
			{
dvander@180
   142
				/* Get the parameter info to copy */
dvander@180
   143
				param = info.recopy[i];
dvander@180
   144
				targ_addr = func->GetAddressOfPushedParam(param);
dvander@180
   145
				orig_addr = info.orig_addrs[param];
dvander@180
   146
				/* Only do the copy for valid targets */
dvander@180
   147
				if (targ_addr && orig_addr)
dvander@180
   148
				{
dvander@180
   149
					if (info.sizes[param] == 1)
dvander@180
   150
					{
dvander@180
   151
						*targ_addr = *orig_addr;
dvander@180
   152
					} else {
dvander@180
   153
						memcpy(targ_addr, orig_addr, info.sizes[param] * sizeof(cell_t));
dvander@180
   154
					}
dvander@180
   155
				}
dvander@180
   156
				/* If this failed, the plugin will most likely be failing as well. */
dvander@180
   157
			}
dvander@180
   158
			save_numcopy = info.numrecopy;
dvander@180
   159
			info.numrecopy = 0;
dvander@180
   160
		}
dvander@180
   161
dvander@180
   162
		/* Call the function and deal with the return value.
dvander@180
   163
		 * :TODO: only pass reader if we know we have an array in the list
dvander@180
   164
		 */
dvander@180
   165
		if ((err=func->Execute(&cur_result, this)) != SP_ERROR_NONE)
dvander@180
   166
		{
dvander@180
   167
			bool handled = false;
dvander@180
   168
			if (filter)
dvander@180
   169
			{
dvander@180
   170
				handled = filter->OnErrorReport(this, func, err);
dvander@180
   171
			}
dvander@180
   172
			if (!handled)
dvander@180
   173
			{
dvander@180
   174
				/* :TODO: invoke global error reporting here */
dvander@180
   175
			}
dvander@180
   176
			/* If we failed, we're not quite done.  The copy chain has been broken.
dvander@180
   177
			 * We have to restore it so past changes will continue to get mirrored.
dvander@180
   178
			 */
dvander@180
   179
			info.numrecopy = save_numcopy;
dvander@180
   180
			failed++;
dvander@180
   181
		} else {
dvander@180
   182
			success++;
dvander@180
   183
			switch (m_ExecType)
dvander@180
   184
			{
dvander@180
   185
			case ET_Event:
dvander@180
   186
				{
dvander@180
   187
					if (cur_result > high_result)
dvander@180
   188
					{
dvander@180
   189
						high_result = cur_result;
dvander@180
   190
					}
dvander@180
   191
					break;
dvander@180
   192
				}
dvander@180
   193
			case ET_Hook:
dvander@180
   194
				{
dvander@180
   195
					if (cur_result > high_result)
dvander@180
   196
					{
dvander@180
   197
						high_result = cur_result;
dvander@180
   198
						if ((ResultType)high_result == Pl_Stop)
dvander@180
   199
						{
dvander@180
   200
							iter = m_functions.end();
dvander@180
   201
							break;
dvander@180
   202
						}
dvander@180
   203
					}
dvander@180
   204
					break;
dvander@180
   205
				}
dvander@180
   206
			case ET_Custom:
dvander@180
   207
				{
dvander@180
   208
					if (filter)
dvander@180
   209
					{
dvander@180
   210
						if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
dvander@180
   211
						{
dvander@180
   212
							iter = m_functions.end();
dvander@180
   213
						}
dvander@180
   214
					}
dvander@180
   215
					break;
dvander@180
   216
				}
dvander@180
   217
			}
dvander@180
   218
		}
dvander@180
   219
	}
dvander@180
   220
dvander@180
   221
	m_NextStack.pop();
dvander@180
   222
dvander@180
   223
	if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
dvander@180
   224
	{
dvander@180
   225
		cur_result = high_result;
dvander@180
   226
	} else if (m_ExecType == ET_Ignore) {
dvander@180
   227
		cur_result = 0;
dvander@180
   228
	}
dvander@180
   229
dvander@180
   230
	*result = cur_result;
dvander@180
   231
dvander@180
   232
	DumpAdditionQueue();
dvander@180
   233
dvander@180
   234
	if (filter)
dvander@180
   235
	{
dvander@180
   236
		filter->OnExecuteEnd(&cur_result, success, failed);
dvander@180
   237
	}
dvander@180
   238
dvander@180
   239
	return SP_ERROR_NONE;
dvander@180
   240
}
dvander@180
   241
dvander@180
   242
int CForward::PushCell(cell_t cell)
dvander@180
   243
{
dvander@180
   244
	if (m_curparam < m_numparams)
dvander@180
   245
	{
dvander@180
   246
		if (m_types[m_curparam] != Param_Cell && m_types[m_curparam] != Param_Any)
dvander@180
   247
		{
dvander@180
   248
			return SetError(SP_ERROR_PARAM);
dvander@180
   249
		}
dvander@180
   250
	} else {
dvander@180
   251
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   252
		{
dvander@180
   253
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   254
		}
dvander@180
   255
	}
dvander@180
   256
dvander@180
   257
	FuncIter iter;
dvander@180
   258
	IPluginFunction *func;
dvander@180
   259
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   260
	{
dvander@180
   261
		func = (*iter);
dvander@180
   262
		func->PushCell(cell);
dvander@180
   263
	}
dvander@180
   264
dvander@180
   265
	m_curparam++;
dvander@180
   266
dvander@180
   267
	return SP_ERROR_NONE;
dvander@180
   268
}
dvander@180
   269
dvander@180
   270
int CForward::PushFloat(float number)
dvander@180
   271
{
dvander@180
   272
	if (m_curparam < m_numparams)
dvander@180
   273
	{
dvander@180
   274
		if (m_types[m_curparam] != Param_Float && m_types[m_curparam] != Param_Any)
dvander@180
   275
		{
dvander@180
   276
			return SetError(SP_ERROR_PARAM);
dvander@180
   277
		}
dvander@180
   278
	} else {
dvander@180
   279
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   280
		{
dvander@180
   281
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   282
		}
dvander@180
   283
	}
dvander@180
   284
dvander@180
   285
	FuncIter iter;
dvander@180
   286
	IPluginFunction *func;
dvander@180
   287
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   288
	{
dvander@180
   289
		func = (*iter);
dvander@180
   290
		func->PushFloat(number);
dvander@180
   291
	}
dvander@180
   292
dvander@180
   293
	m_curparam++;
dvander@180
   294
dvander@180
   295
	return SP_ERROR_NONE;
dvander@180
   296
}
dvander@180
   297
dvander@180
   298
int CForward::PushCellByRef(cell_t *cell, int flags)
dvander@180
   299
{
dvander@180
   300
	if (m_curparam < m_numparams)
dvander@180
   301
	{
dvander@180
   302
		if (m_types[m_curparam] != Param_CellByRef && m_types[m_curparam] != Param_Any)
dvander@180
   303
		{
dvander@180
   304
			return SetError(SP_ERROR_PARAM);
dvander@180
   305
		}
dvander@180
   306
	} else {
dvander@180
   307
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   308
		{
dvander@180
   309
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   310
		}
dvander@180
   311
	}
dvander@180
   312
dvander@180
   313
	if (flags & SMFUNC_COPYBACK_ALWAYS)
dvander@180
   314
	{
dvander@180
   315
		_Int_PushArray(cell, 1, flags);
dvander@180
   316
	} else {
dvander@180
   317
		FuncIter iter;
dvander@180
   318
		IPluginFunction *func;
dvander@180
   319
		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   320
		{
dvander@180
   321
			func = (*iter);
dvander@180
   322
			func->PushCellByRef(cell, flags);
dvander@180
   323
		}
dvander@180
   324
	}
dvander@180
   325
dvander@180
   326
	m_curparam++;
dvander@180
   327
dvander@180
   328
	return SP_ERROR_NONE;
dvander@180
   329
}
dvander@180
   330
dvander@180
   331
int CForward::PushFloatByRef(float *num, int flags)
dvander@180
   332
{
dvander@180
   333
	if (m_curparam < m_numparams)
dvander@180
   334
	{
dvander@180
   335
		if (m_types[m_curparam] != Param_FloatByRef && m_types[m_curparam] != Param_Any)
dvander@180
   336
		{
dvander@180
   337
			return SetError(SP_ERROR_PARAM);
dvander@180
   338
		}
dvander@180
   339
	} else {
dvander@180
   340
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   341
		{
dvander@180
   342
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   343
		}
dvander@180
   344
	}
dvander@180
   345
dvander@180
   346
	if (flags & SMFUNC_COPYBACK_ALWAYS)
dvander@180
   347
	{
dvander@180
   348
		_Int_PushArray((cell_t *)num, 1, flags);
dvander@180
   349
	} else {
dvander@180
   350
		FuncIter iter;
dvander@180
   351
		IPluginFunction *func;
dvander@180
   352
		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   353
		{
dvander@180
   354
			func = (*iter);
dvander@180
   355
			func->PushFloatByRef(num, flags);
dvander@180
   356
		}
dvander@180
   357
	}
dvander@180
   358
dvander@180
   359
	m_curparam++;
dvander@180
   360
dvander@180
   361
	return SP_ERROR_NONE;
dvander@180
   362
}
dvander@180
   363
dvander@180
   364
int CForward::PushCells(cell_t array[], unsigned int numcells, bool each)
dvander@180
   365
{
dvander@180
   366
	if (each)
dvander@180
   367
	{
dvander@180
   368
		/* Type check each cell if we need to! */
dvander@180
   369
		if (m_curparam + numcells >= m_numparams && !m_varargs)
dvander@180
   370
		{
dvander@180
   371
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   372
		} else {
dvander@180
   373
			for (unsigned int i=m_curparam; i<m_numparams; i++)
dvander@180
   374
			{
dvander@180
   375
				if (m_types[i] != Param_Any || m_types[i] != Param_Cell)
dvander@180
   376
				{
dvander@180
   377
					return SetError(SP_ERROR_PARAM);
dvander@180
   378
				}
dvander@180
   379
			}
dvander@180
   380
		}
dvander@180
   381
	} else {
dvander@180
   382
		if (m_curparam < m_numparams)
dvander@180
   383
		{
dvander@180
   384
			if (m_types[m_curparam] != Param_Any || m_types[m_curparam] == Param_Array)
dvander@180
   385
			{
dvander@180
   386
				return SetError(SP_ERROR_PARAM);
dvander@180
   387
			}
dvander@180
   388
		} else {
dvander@180
   389
			if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   390
			{
dvander@180
   391
				return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   392
			}
dvander@180
   393
		}
dvander@180
   394
	}
dvander@180
   395
dvander@180
   396
	FuncIter iter;
dvander@180
   397
	IPluginFunction *func;
dvander@180
   398
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   399
	{
dvander@180
   400
		func = (*iter);
dvander@180
   401
		func->PushCells(array, numcells, each);
dvander@180
   402
	}
dvander@180
   403
dvander@180
   404
	m_curparam += each ? numcells : 1;
dvander@180
   405
	
dvander@180
   406
	return SP_ERROR_NONE;
dvander@180
   407
}
dvander@180
   408
dvander@180
   409
void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   410
{
dvander@180
   411
	FuncIter iter;
dvander@180
   412
	IPluginFunction *func;
dvander@180
   413
	if (flags & SMFUNC_COPYBACK_ALWAYS)
dvander@180
   414
	{
dvander@180
   415
		/* As a special optimization, we create blank default arrays because they will be 
dvander@180
   416
		* copied over anyway!
dvander@180
   417
		*/
dvander@180
   418
		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   419
		{
dvander@180
   420
			func = (*iter);
dvander@180
   421
			func->PushArray(NULL, cells, NULL, flags);
dvander@180
   422
		}
dvander@180
   423
		m_CopyBacks.recopy[m_CopyBacks.numrecopy++] = m_curparam;
dvander@180
   424
		m_CopyBacks.orig_addrs[m_curparam] = inarray;
dvander@180
   425
		m_CopyBacks.sizes[m_curparam] = cells;
dvander@180
   426
	} else {
dvander@180
   427
		for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   428
		{
dvander@180
   429
			func = (*iter);
dvander@180
   430
			func->PushArray(inarray, cells, NULL, flags);
dvander@180
   431
		}
dvander@180
   432
	}
dvander@180
   433
}
dvander@180
   434
dvander@180
   435
int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
dvander@180
   436
{
dvander@180
   437
	/* We don't allow this here */
dvander@180
   438
	if (!inarray)
dvander@180
   439
	{
dvander@180
   440
		return SetError(SP_ERROR_PARAM);
dvander@180
   441
	}
dvander@180
   442
dvander@180
   443
	if (m_curparam < m_numparams)
dvander@180
   444
	{
dvander@180
   445
		if (m_types[m_curparam] != Param_Any || m_types[m_curparam] == Param_Array)
dvander@180
   446
		{
dvander@180
   447
			return SetError(SP_ERROR_PARAM);
dvander@180
   448
		}
dvander@180
   449
	} else {
dvander@180
   450
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   451
		{
dvander@180
   452
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   453
		}
dvander@180
   454
	}
dvander@180
   455
dvander@180
   456
	if (phys_addr)
dvander@180
   457
	{
dvander@180
   458
		*phys_addr = NULL;
dvander@180
   459
	}
dvander@180
   460
dvander@180
   461
	_Int_PushArray(inarray, cells, flags);
dvander@180
   462
dvander@180
   463
	m_curparam++;
dvander@180
   464
dvander@180
   465
	return SP_ERROR_NONE;
dvander@180
   466
}
dvander@180
   467
dvander@180
   468
int CForward::PushString(const char *string)
dvander@180
   469
{
dvander@180
   470
	if (m_curparam < m_numparams)
dvander@180
   471
	{
dvander@180
   472
		if (m_types[m_curparam] != Param_Any || m_types[m_curparam] == Param_String)
dvander@180
   473
		{
dvander@180
   474
			return SetError(SP_ERROR_PARAM);
dvander@180
   475
		}
dvander@180
   476
	} else {
dvander@180
   477
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   478
		{
dvander@180
   479
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   480
		}
dvander@180
   481
	}
dvander@180
   482
dvander@180
   483
	FuncIter iter;
dvander@180
   484
	IPluginFunction *func;
dvander@180
   485
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   486
	{
dvander@180
   487
		func = (*iter);
dvander@180
   488
		func->PushString(string);
dvander@180
   489
	}
dvander@180
   490
dvander@180
   491
	m_curparam++;
dvander@180
   492
dvander@180
   493
	return SP_ERROR_NONE;
dvander@180
   494
}
dvander@180
   495
dvander@180
   496
int CForward::PushStringByRef(char *string, int flags)
dvander@180
   497
{
dvander@180
   498
	if (m_curparam < m_numparams)
dvander@180
   499
	{
dvander@180
   500
		if (m_types[m_curparam] != Param_Any || m_types[m_curparam] == Param_String)
dvander@180
   501
		{
dvander@180
   502
			return SetError(SP_ERROR_PARAM);
dvander@180
   503
		}
dvander@180
   504
	} else {
dvander@180
   505
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   506
		{
dvander@180
   507
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   508
		}
dvander@180
   509
	}
dvander@180
   510
dvander@180
   511
	FuncIter iter;
dvander@180
   512
	IPluginFunction *func;
dvander@180
   513
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   514
	{
dvander@180
   515
		func = (*iter);
dvander@180
   516
		func->PushStringByRef(string, flags);
dvander@180
   517
	}
dvander@180
   518
dvander@180
   519
	m_curparam++;
dvander@180
   520
dvander@180
   521
	return SP_ERROR_NONE;
dvander@180
   522
}
dvander@180
   523
dvander@180
   524
void CForward::Cancel()
dvander@180
   525
{
dvander@180
   526
	if (!m_curparam)
dvander@180
   527
	{
dvander@180
   528
		return;
dvander@180
   529
	}
dvander@180
   530
dvander@180
   531
	FuncIter iter;
dvander@180
   532
	IPluginFunction *func;
dvander@180
   533
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   534
	{
dvander@180
   535
		func = (*iter);
dvander@180
   536
		func->Cancel();
dvander@180
   537
	}
dvander@180
   538
dvander@180
   539
	m_CopyBacks.numrecopy = 0;
dvander@180
   540
dvander@180
   541
	DumpAdditionQueue();
dvander@180
   542
dvander@180
   543
	m_errstate = SP_ERROR_NONE;
dvander@180
   544
}
dvander@180
   545
dvander@180
   546
bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
dvander@180
   547
{
dvander@180
   548
	IPlugin *pPlugin = g_PluginMngr.FindPluginByContext(ctx);
dvander@180
   549
	if (!pPlugin)
dvander@180
   550
	{
dvander@180
   551
		return false;
dvander@180
   552
	}
dvander@180
   553
dvander@180
   554
	IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
dvander@180
   555
	if (!pFunc)
dvander@180
   556
	{
dvander@180
   557
		return false;
dvander@180
   558
	}
dvander@180
   559
dvander@180
   560
	return AddFunction(pFunc);
dvander@180
   561
}
dvander@180
   562
dvander@180
   563
bool CForward::RemoveFunction(IPluginFunction *func)
dvander@180
   564
{
dvander@180
   565
	bool found = false;
dvander@180
   566
	FuncIter iter;
dvander@180
   567
	IPluginFunction *pNext = NULL;
dvander@180
   568
dvander@180
   569
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   570
	{
dvander@180
   571
		if ((*iter) == func)
dvander@180
   572
		{
dvander@180
   573
			found = true;
dvander@180
   574
			/* If this iterator is being used, swap in a new one !*/
dvander@180
   575
			iter = m_functions.erase(iter);
dvander@180
   576
		} else {
dvander@180
   577
			iter++;
dvander@180
   578
		}
dvander@180
   579
	}
dvander@180
   580
dvander@180
   581
	/* Just in case */
dvander@180
   582
	m_AddQueue.remove(func);
dvander@180
   583
	
dvander@180
   584
	/* Cancel a call, if any */
dvander@180
   585
	if (found && (!m_NextStack.empty() || m_curparam))
dvander@180
   586
	{
dvander@180
   587
		func->Cancel();
dvander@180
   588
	}
dvander@180
   589
dvander@180
   590
	return found;
dvander@180
   591
}
dvander@180
   592
dvander@180
   593
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
dvander@180
   594
{
dvander@180
   595
	FuncIter iter;
dvander@180
   596
	IPluginFunction *func;
dvander@180
   597
	unsigned int removed = 0;
dvander@180
   598
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   599
	{
dvander@180
   600
		func = (*iter);
dvander@180
   601
		if (func->GetParentPlugin() == plugin)
dvander@180
   602
		{
dvander@180
   603
			iter = m_functions.erase(iter);
dvander@180
   604
			removed++;
dvander@180
   605
		} else {
dvander@180
   606
			iter++;
dvander@180
   607
		}
dvander@180
   608
	}
dvander@180
   609
dvander@180
   610
	for (iter=m_AddQueue.begin(); iter!=m_AddQueue.end();)
dvander@180
   611
	{
dvander@180
   612
		func = (*iter);
dvander@180
   613
		if (func->GetParentPlugin() == plugin)
dvander@180
   614
		{
dvander@180
   615
			/* Don't count these toward the total */
dvander@180
   616
			iter = m_functions.erase(iter);
dvander@180
   617
		} else {
dvander@180
   618
			iter++;
dvander@180
   619
		}
dvander@180
   620
	}
dvander@180
   621
dvander@180
   622
	return removed;
dvander@180
   623
}
dvander@180
   624
dvander@180
   625
void CForward::DumpAdditionQueue()
dvander@180
   626
{
dvander@180
   627
	FuncIter iter = m_AddQueue.begin();
dvander@180
   628
	while (iter != m_AddQueue.end())
dvander@180
   629
	{
dvander@180
   630
		m_functions.push_back((*iter));
dvander@180
   631
		//:TODO: eventually we will tell the plugin we're using it
dvander@180
   632
		iter = m_AddQueue.erase(iter);
dvander@180
   633
	}
dvander@180
   634
}
dvander@180
   635
dvander@180
   636
bool CForward::AddFunction(IPluginFunction *func)
dvander@180
   637
{
dvander@180
   638
	if (m_curparam)
dvander@180
   639
	{
dvander@180
   640
		return false;
dvander@180
   641
	}
dvander@180
   642
dvander@180
   643
	if (!m_NextStack.empty())
dvander@180
   644
	{
dvander@180
   645
		m_AddQueue.push_back(func);
dvander@180
   646
	} else {
dvander@180
   647
		//:TODO: eventually we will tell the plugin we're using it
dvander@180
   648
		m_functions.push_back(func);
dvander@180
   649
	}
dvander@180
   650
dvander@180
   651
	return true;
dvander@180
   652
}
dvander@180
   653
dvander@180
   654
const char *CForward::GetForwardName()
dvander@180
   655
{
dvander@180
   656
	return m_name;
dvander@180
   657
}
dvander@180
   658
dvander@180
   659
unsigned int CForward::GetFunctionCount()
dvander@180
   660
{
dvander@180
   661
	return m_functions.size();
dvander@180
   662
}
dvander@180
   663
dvander@180
   664
ExecType CForward::GetExecType()
dvander@180
   665
{
dvander@180
   666
	return m_ExecType;
dvander@180
   667
}