core/logic/smn_adt_stack.cpp
author David Anderson <dvander@alliedmods.net>
Thu Aug 08 22:02:42 2013 -0700 (2013-08-08)
changeset 3980 dc7dfcd855dc
parent 2726 c96f3fab8211
permissions -rw-r--r--
More Windows build fix.
dvander@2726
     1
/**
dvander@2726
     2
* vim: set ts=4 :
dvander@2726
     3
* =============================================================================
dvander@2726
     4
* SourceMod
dvander@2726
     5
* Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2726
     6
* =============================================================================
dvander@2726
     7
*
dvander@2726
     8
* This program is free software; you can redistribute it and/or modify it under
dvander@2726
     9
* the terms of the GNU General Public License, version 3.0, as published by the
dvander@2726
    10
* Free Software Foundation.
dvander@2726
    11
* 
dvander@2726
    12
* This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2726
    13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2726
    14
* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2726
    15
* details.
dvander@2726
    16
*
dvander@2726
    17
* You should have received a copy of the GNU General Public License along with
dvander@2726
    18
* this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2726
    19
*
dvander@2726
    20
* As a special exception, AlliedModders LLC gives you permission to link the
dvander@2726
    21
* code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2726
    22
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2726
    23
* by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2726
    24
* all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2726
    25
* this exception to all derivative works.  AlliedModders LLC defines further
dvander@2726
    26
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2726
    27
* or <http://www.sourcemod.net/license.php>.
dvander@2726
    28
*
dvander@2726
    29
* Version: $Id$
dvander@2726
    30
*/
dvander@2726
    31
dvander@2726
    32
#include <stdlib.h>
dvander@2726
    33
#include "common_logic.h"
dvander@2726
    34
#include "CellArray.h"
dvander@2726
    35
dvander@2726
    36
HandleType_t htCellStack;
dvander@2726
    37
dvander@2726
    38
class CellStackHelpers : 
dvander@2726
    39
	public SMGlobalClass,
dvander@2726
    40
	public IHandleTypeDispatch
dvander@2726
    41
{
dvander@2726
    42
public: //SMGlobalClass
dvander@2726
    43
	void OnSourceModAllInitialized()
dvander@2726
    44
	{
dvander@2726
    45
		htCellStack = handlesys->CreateType("CellStack", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@2726
    46
	}
dvander@2726
    47
	void OnSourceModShutdown()
dvander@2726
    48
	{
dvander@2726
    49
		handlesys->RemoveType(htCellStack, g_pCoreIdent);
dvander@2726
    50
	}
dvander@2726
    51
public: //IHandleTypeDispatch
dvander@2726
    52
	void OnHandleDestroy(HandleType_t type, void *object)
dvander@2726
    53
	{
dvander@2726
    54
		CellArray *array = (CellArray *)object;
dvander@2726
    55
		delete array;
dvander@2726
    56
	}
dvander@2726
    57
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@2726
    58
	{
dvander@2726
    59
		CellArray *pArray = (CellArray *)object;
dvander@2726
    60
		*pSize = sizeof(CellArray) + pArray->mem_usage();
dvander@2726
    61
		return true;
dvander@2726
    62
	}
dvander@2726
    63
} s_CellStackHelpers;
dvander@2726
    64
dvander@2726
    65
static cell_t CreateStack(IPluginContext *pContext, const cell_t *params)
dvander@2726
    66
{
dvander@2726
    67
	if (params[1] < 1)
dvander@2726
    68
	{
dvander@2726
    69
		return pContext->ThrowNativeError("Invalid block size (must be > 0)");
dvander@2726
    70
	}
dvander@2726
    71
dvander@2726
    72
	CellArray *array = new CellArray(params[1]);
dvander@2726
    73
dvander@2726
    74
	Handle_t hndl = handlesys->CreateHandle(htCellStack, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@2726
    75
	if (!hndl)
dvander@2726
    76
	{
dvander@2726
    77
		delete array;
dvander@2726
    78
	}
dvander@2726
    79
dvander@2726
    80
	return hndl;
dvander@2726
    81
}
dvander@2726
    82
dvander@2726
    83
static cell_t PushStackCell(IPluginContext *pContext, const cell_t *params)
dvander@2726
    84
{
dvander@2726
    85
	CellArray *array;
dvander@2726
    86
	HandleError err;
dvander@2726
    87
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
    88
dvander@2726
    89
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
    90
		!= HandleError_None)
dvander@2726
    91
	{
dvander@2726
    92
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
    93
	}
dvander@2726
    94
dvander@2726
    95
	cell_t *blk = array->push();
dvander@2726
    96
	if (!blk)
dvander@2726
    97
	{
dvander@2726
    98
		return pContext->ThrowNativeError("Failed to grow stack");
dvander@2726
    99
	}
dvander@2726
   100
dvander@2726
   101
	*blk = params[2];
dvander@2726
   102
dvander@2726
   103
	return 1;
dvander@2726
   104
}
dvander@2726
   105
dvander@2726
   106
static cell_t PushStackString(IPluginContext *pContext, const cell_t *params)
dvander@2726
   107
{
dvander@2726
   108
	CellArray *array;
dvander@2726
   109
	HandleError err;
dvander@2726
   110
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   111
dvander@2726
   112
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   113
		!= HandleError_None)
dvander@2726
   114
	{
dvander@2726
   115
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   116
	}
dvander@2726
   117
dvander@2726
   118
	cell_t *blk = array->push();
dvander@2726
   119
	if (!blk)
dvander@2726
   120
	{
dvander@2726
   121
		return pContext->ThrowNativeError("Failed to grow stack");
dvander@2726
   122
	}
dvander@2726
   123
dvander@2726
   124
	char *str;
dvander@2726
   125
	pContext->LocalToString(params[2], &str);
dvander@2726
   126
dvander@2726
   127
	smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
dvander@2726
   128
dvander@2726
   129
	return 1;
dvander@2726
   130
}
dvander@2726
   131
dvander@2726
   132
static cell_t PushStackArray(IPluginContext *pContext, const cell_t *params)
dvander@2726
   133
{
dvander@2726
   134
	CellArray *array;
dvander@2726
   135
	HandleError err;
dvander@2726
   136
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   137
dvander@2726
   138
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   139
		!= HandleError_None)
dvander@2726
   140
	{
dvander@2726
   141
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   142
	}
dvander@2726
   143
dvander@2726
   144
	cell_t *blk = array->push();
dvander@2726
   145
	if (!blk)
dvander@2726
   146
	{
dvander@2726
   147
		return pContext->ThrowNativeError("Failed to grow array");
dvander@2726
   148
	}
dvander@2726
   149
dvander@2726
   150
	cell_t *addr;
dvander@2726
   151
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@2726
   152
dvander@2726
   153
	size_t indexes = array->blocksize();
dvander@2726
   154
	if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
dvander@2726
   155
	{
dvander@2726
   156
		indexes = params[3];
dvander@2726
   157
	}
dvander@2726
   158
dvander@2726
   159
	memcpy(blk, addr, sizeof(cell_t) * indexes);
dvander@2726
   160
dvander@2726
   161
	return 1;
dvander@2726
   162
}
dvander@2726
   163
dvander@2726
   164
static cell_t PopStackCell(IPluginContext *pContext, const cell_t *params)
dvander@2726
   165
{
dvander@2726
   166
	size_t idx;
dvander@2726
   167
	HandleError err;
dvander@2726
   168
	CellArray *array;
dvander@2726
   169
	cell_t *blk, *buffer;
dvander@2726
   170
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   171
dvander@2726
   172
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   173
		!= HandleError_None)
dvander@2726
   174
	{
dvander@2726
   175
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   176
	}
dvander@2726
   177
dvander@2726
   178
	if (array->size() == 0)
dvander@2726
   179
	{
dvander@2726
   180
		return 0;
dvander@2726
   181
	}
dvander@2726
   182
dvander@2726
   183
	pContext->LocalToPhysAddr(params[2], &buffer);
dvander@2726
   184
dvander@2726
   185
	blk = array->at(array->size() - 1);
dvander@2726
   186
	idx = (size_t)params[3];
dvander@2726
   187
dvander@2726
   188
	if (params[4] == 0)
dvander@2726
   189
	{
dvander@2726
   190
		if (idx >= array->blocksize())
dvander@2726
   191
		{
dvander@2726
   192
			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
dvander@2726
   193
		}
dvander@2726
   194
		*buffer = blk[idx];
dvander@2726
   195
	}
dvander@2726
   196
	else
dvander@2726
   197
	{
dvander@2726
   198
		if (idx >= array->blocksize() * 4)
dvander@2726
   199
		{
dvander@2726
   200
			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
dvander@2726
   201
		}
dvander@2726
   202
		*buffer = (cell_t)*((char *)blk + idx);
dvander@2726
   203
	}
dvander@2726
   204
dvander@2726
   205
	array->remove(array->size() - 1);
dvander@2726
   206
dvander@2726
   207
	return 1;
dvander@2726
   208
}
dvander@2726
   209
dvander@2726
   210
static cell_t PopStackString(IPluginContext *pContext, const cell_t *params)
dvander@2726
   211
{
dvander@2726
   212
	HandleError err;
dvander@2726
   213
	CellArray *array;
dvander@2726
   214
	size_t idx, numWritten;
dvander@2726
   215
	cell_t *blk, *pWritten;
dvander@2726
   216
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   217
dvander@2726
   218
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   219
		!= HandleError_None)
dvander@2726
   220
	{
dvander@2726
   221
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   222
	}
dvander@2726
   223
dvander@2726
   224
	if (array->size() == 0)
dvander@2726
   225
	{
dvander@2726
   226
		return 0;
dvander@2726
   227
	}
dvander@2726
   228
dvander@2726
   229
	idx = array->size() - 1;
dvander@2726
   230
	blk = array->at(idx);
dvander@2726
   231
	pContext->StringToLocalUTF8(params[2], params[3], (char *)blk, &numWritten);
dvander@2726
   232
	pContext->LocalToPhysAddr(params[4], &pWritten);
dvander@2726
   233
	*pWritten = (cell_t)numWritten;
dvander@2726
   234
	array->remove(idx);
dvander@2726
   235
dvander@2726
   236
	return 1;
dvander@2726
   237
}
dvander@2726
   238
dvander@2726
   239
static cell_t PopStackArray(IPluginContext *pContext, const cell_t *params)
dvander@2726
   240
{
dvander@2726
   241
	size_t idx;
dvander@2726
   242
	cell_t *blk;
dvander@2726
   243
	cell_t *addr;
dvander@2726
   244
	size_t indexes;
dvander@2726
   245
	HandleError err;
dvander@2726
   246
	CellArray *array;
dvander@2726
   247
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   248
dvander@2726
   249
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   250
		!= HandleError_None)
dvander@2726
   251
	{
dvander@2726
   252
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   253
	}
dvander@2726
   254
dvander@2726
   255
	if (array->size() == 0)
dvander@2726
   256
	{
dvander@2726
   257
		return 0;
dvander@2726
   258
	}
dvander@2726
   259
dvander@2726
   260
	idx = array->size() - 1;
dvander@2726
   261
	blk = array->at(idx);
dvander@2726
   262
	indexes = array->blocksize();
dvander@2726
   263
dvander@2726
   264
	if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
dvander@2726
   265
	{
dvander@2726
   266
		indexes = params[3];
dvander@2726
   267
	}
dvander@2726
   268
dvander@2726
   269
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@2726
   270
	memcpy(addr, blk, sizeof(cell_t) * indexes);
dvander@2726
   271
	array->remove(idx);
dvander@2726
   272
dvander@2726
   273
	return indexes;
dvander@2726
   274
}
dvander@2726
   275
dvander@2726
   276
static cell_t IsStackEmpty(IPluginContext *pContext, const cell_t *params)
dvander@2726
   277
{
dvander@2726
   278
	HandleError err;
dvander@2726
   279
	CellArray *array;
dvander@2726
   280
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@2726
   281
dvander@2726
   282
	if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) 
dvander@2726
   283
		!= HandleError_None)
dvander@2726
   284
	{
dvander@2726
   285
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@2726
   286
	}
dvander@2726
   287
dvander@2726
   288
	if (array->size() == 0)
dvander@2726
   289
	{
dvander@2726
   290
		return 1;
dvander@2726
   291
	}
dvander@2726
   292
dvander@2726
   293
	return 0;
dvander@2726
   294
}
dvander@2726
   295
dvander@2726
   296
REGISTER_NATIVES(cellStackNatives)
dvander@2726
   297
{
dvander@2726
   298
	{"CreateStack",					CreateStack},
dvander@2726
   299
	{"IsStackEmpty",				IsStackEmpty},
dvander@2726
   300
	{"PopStackArray",				PopStackArray},
dvander@2726
   301
	{"PopStackCell",				PopStackCell},
dvander@2726
   302
	{"PopStackString",				PopStackString},
dvander@2726
   303
	{"PushStackArray",				PushStackArray},
dvander@2726
   304
	{"PushStackCell",				PushStackCell},
dvander@2726
   305
	{"PushStackString",				PushStackString},
dvander@2726
   306
	{NULL,							NULL},
dvander@2726
   307
};