core/smn_adt_array.cpp
author Borja Ferrer <faluco@alliedmods.net>
Fri Nov 16 21:34:29 2007 +0000 (2007-11-16)
changeset 1686 185cac1820fe
parent 1664 e054be79e28a
child 1766 d30c252089be
permissions -rw-r--r--
fixed amb1164, SM was crashing due to interface changes from valve (this change is just to make the build update using the latest sdk)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include <malloc.h>
    33 #include "sm_globals.h"
    34 #include "sm_stringutil.h"
    35 #include "CellArray.h"
    36 #include "HandleSys.h"
    37 
    38 HandleType_t htCellArray;
    39 
    40 class CellArrayHelpers : 
    41 	public SMGlobalClass,
    42 	public IHandleTypeDispatch
    43 {
    44 public: //SMGlobalClass
    45 	void OnSourceModAllInitialized()
    46 	{
    47 		htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    48 	}
    49 	void OnSourceModShutdown()
    50 	{
    51 		g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
    52 	}
    53 public: //IHandleTypeDispatch
    54 	void OnHandleDestroy(HandleType_t type, void *object)
    55 	{
    56 		CellArray *array = (CellArray *)object;
    57 		delete array;
    58 	}
    59 } s_CellArrayHelpers;
    60 
    61 static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
    62 {
    63 	if (!params[1])
    64 	{
    65 		return pContext->ThrowNativeError("Invalid block size (must be > 0)");
    66 	}
    67 
    68 	CellArray *array = new CellArray(params[1]);
    69 
    70 	if (params[2])
    71 	{
    72 		array->resize(params[2]);
    73 	}
    74 	
    75 	Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
    76 	if (!hndl)
    77 	{
    78 		delete array;
    79 	}
    80 
    81 	return hndl;
    82 }
    83 
    84 static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
    85 {
    86 	CellArray *array;
    87 	HandleError err;
    88 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
    89 
    90 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
    91 		!= HandleError_None)
    92 	{
    93 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
    94 	}
    95 
    96 	array->clear();
    97 	
    98 	return 1;
    99 }
   100 
   101 static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
   102 {
   103 	CellArray *array;
   104 	HandleError err;
   105 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   106 
   107 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   108 		!= HandleError_None)
   109 	{
   110 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   111 	}
   112 
   113 	if (!array->resize(params[2]))
   114 	{
   115 		return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
   116 	}
   117 
   118 	return 1;
   119 }
   120 
   121 static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
   122 {
   123 	CellArray *array;
   124 	HandleError err;
   125 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   126 
   127 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   128 		!= HandleError_None)
   129 	{
   130 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   131 	}
   132 
   133 	return (cell_t)array->size();
   134 }
   135 
   136 static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
   137 {
   138 	CellArray *array;
   139 	HandleError err;
   140 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   141 
   142 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   143 		!= HandleError_None)
   144 	{
   145 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   146 	}
   147 
   148 	cell_t *blk = array->push();
   149 	if (!blk)
   150 	{
   151 		return pContext->ThrowNativeError("Failed to grow array");
   152 	}
   153 
   154 	*blk = params[2];
   155 
   156 	return (cell_t)(array->size() - 1);
   157 }
   158 
   159 static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
   160 {
   161 	CellArray *array;
   162 	HandleError err;
   163 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   164 
   165 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   166 		!= HandleError_None)
   167 	{
   168 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   169 	}
   170 
   171 	cell_t *blk = array->push();
   172 	if (!blk)
   173 	{
   174 		return pContext->ThrowNativeError("Failed to grow array");
   175 	}
   176 
   177 	char *str;
   178 	pContext->LocalToString(params[2], &str);
   179 
   180 	strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   181 
   182 	return (cell_t)(array->size() - 1);
   183 }
   184 
   185 static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
   186 {
   187 	CellArray *array;
   188 	HandleError err;
   189 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   190 
   191 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   192 		!= HandleError_None)
   193 	{
   194 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   195 	}
   196 
   197 	cell_t *blk = array->push();
   198 	if (!blk)
   199 	{
   200 		return pContext->ThrowNativeError("Failed to grow array");
   201 	}
   202 
   203 	cell_t *addr;
   204 	pContext->LocalToPhysAddr(params[2], &addr);
   205 
   206 	size_t indexes = array->blocksize();
   207 	if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
   208 	{
   209 		indexes = params[3];
   210 	}
   211 
   212 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   213 
   214 	return (cell_t)(array->size() - 1);
   215 }
   216 
   217 static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
   218 {
   219 	CellArray *array;
   220 	HandleError err;
   221 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   222 
   223 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   224 		!= HandleError_None)
   225 	{
   226 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   227 	}
   228 
   229 	size_t idx = (size_t)params[2];
   230 	if (idx >= array->size())
   231 	{
   232 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   233 	}
   234 
   235 	cell_t *blk = array->at(idx);
   236 
   237 	idx = (size_t)params[3];
   238 	if (params[4] == 0)
   239 	{
   240 		if (idx >= array->blocksize())
   241 		{
   242 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   243 		}
   244 		return blk[idx];
   245 	} else {
   246 		if (idx >= array->blocksize() * 4)
   247 		{
   248 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   249 		}
   250 		return (cell_t)*((char *)blk + idx);
   251 	}
   252 
   253 	return 0;
   254 }
   255 
   256 static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
   257 {
   258 	CellArray *array;
   259 	HandleError err;
   260 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   261 
   262 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   263 		!= HandleError_None)
   264 	{
   265 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   266 	}
   267 
   268 	size_t idx = (size_t)params[2];
   269 	if (idx >= array->size())
   270 	{
   271 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   272 	}
   273 
   274 	cell_t *blk = array->at(idx);
   275 	size_t numWritten = 0;
   276 
   277 	pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
   278 
   279 	return numWritten;
   280 }
   281 
   282 static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
   283 {
   284 	CellArray *array;
   285 	HandleError err;
   286 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   287 
   288 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   289 		!= HandleError_None)
   290 	{
   291 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   292 	}
   293 
   294 	size_t idx = (size_t)params[2];
   295 	if (idx >= array->size())
   296 	{
   297 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   298 	}
   299 
   300 	cell_t *blk = array->at(idx);
   301 	size_t indexes = array->blocksize();
   302 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   303 	{
   304 		indexes = params[4];
   305 	}
   306 
   307 	cell_t *addr;
   308 	pContext->LocalToPhysAddr(params[3], &addr);
   309 
   310 	memcpy(addr, blk, sizeof(cell_t) * indexes);
   311 
   312 	return indexes;
   313 }
   314 
   315 static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
   316 {
   317 	CellArray *array;
   318 	HandleError err;
   319 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   320 
   321 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   322 		!= HandleError_None)
   323 	{
   324 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   325 	}
   326 
   327 	size_t idx = (size_t)params[2];
   328 	if (idx >= array->size())
   329 	{
   330 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   331 	}
   332 
   333 	cell_t *blk = array->at(idx);
   334 
   335 	idx = (size_t)params[4];
   336 	if (params[5] == 0)
   337 	{
   338 		if (idx >= array->blocksize())
   339 		{
   340 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   341 		}
   342 		blk[idx] = params[3];
   343 	} else {
   344 		if (idx >= array->blocksize() * 4)
   345 		{
   346 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   347 		}
   348 		*((char *)blk + idx) = (char)params[3];
   349 	}
   350 
   351 	return 1;
   352 }
   353 
   354 static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
   355 {
   356 	CellArray *array;
   357 	HandleError err;
   358 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   359 
   360 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   361 		!= HandleError_None)
   362 	{
   363 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   364 	}
   365 
   366 	size_t idx = (size_t)params[2];
   367 	if (idx >= array->size())
   368 	{
   369 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   370 	}
   371 
   372 	cell_t *blk = array->at(idx);
   373 
   374 	char *str;
   375 	pContext->LocalToString(params[3], &str);
   376 
   377 	return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   378 }
   379 
   380 static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
   381 {
   382 	CellArray *array;
   383 	HandleError err;
   384 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   385 
   386 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   387 		!= HandleError_None)
   388 	{
   389 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   390 	}
   391 
   392 	size_t idx = (size_t)params[2];
   393 	if (idx >= array->size())
   394 	{
   395 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   396 	}
   397 
   398 	cell_t *blk = array->at(idx);
   399 	size_t indexes = array->blocksize();
   400 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   401 	{
   402 		indexes = params[4];
   403 	}
   404 
   405 	cell_t *addr;
   406 	pContext->LocalToPhysAddr(params[3], &addr);
   407 
   408 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   409 
   410 	return indexes;
   411 }
   412 
   413 static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
   414 {
   415 	CellArray *array;
   416 	HandleError err;
   417 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   418 
   419 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   420 		!= HandleError_None)
   421 	{
   422 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   423 	}
   424 
   425 	size_t idx = (size_t)params[2];
   426 	if (idx >= array->size())
   427 	{
   428 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   429 	}
   430 
   431 	array->insert_at(idx);
   432 
   433 	return 1;
   434 }
   435 
   436 static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
   437 {
   438 	CellArray *array;
   439 	HandleError err;
   440 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   441 
   442 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   443 		!= HandleError_None)
   444 	{
   445 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   446 	}
   447 
   448 	size_t idx = (size_t)params[2];
   449 	if (idx >= array->size())
   450 	{
   451 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   452 	}
   453 
   454 	array->remove(idx);
   455 
   456 	return 1;
   457 }
   458 
   459 static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
   460 {
   461 	CellArray *array;
   462 	HandleError err;
   463 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   464 
   465 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   466 		!= HandleError_None)
   467 	{
   468 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   469 	}
   470 
   471 	size_t idx1 = (size_t)params[2];
   472 	size_t idx2 = (size_t)params[3];
   473 	if (idx1 >= array->size())
   474 	{
   475 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
   476 	}
   477 	if (idx2 >= array->size())
   478 	{
   479 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
   480 	}
   481 
   482 	array->swap(idx1, idx2);
   483 
   484 	return 1;
   485 }
   486 
   487 static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
   488 {
   489 	CellArray *oldArray;
   490 	HandleError err;
   491 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   492 
   493 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray)) 
   494 		!= HandleError_None)
   495 	{
   496 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   497 	}
   498 
   499 	CellArray *array = oldArray->clone();
   500 	
   501 	Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
   502 	if (!hndl)
   503 	{
   504 		delete array;
   505 	}
   506 
   507 	return hndl;
   508 }
   509 
   510 static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
   511 {
   512 	CellArray *array;
   513 	HandleError err;
   514 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   515 
   516 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   517 		!= HandleError_None)
   518 	{
   519 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   520 	}
   521 
   522 	char *str;
   523 	pContext->LocalToString(params[2], &str);
   524 
   525 	for (unsigned int i = 0; i < array->size(); i++)
   526 	{
   527 		const char *array_str = (const char *)array->at(i);
   528 		if (strcmp(str, array_str) == 0)
   529 		{
   530 			return (cell_t) i;
   531 		}
   532 	}
   533 
   534 	return -1;
   535 }
   536 
   537 static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
   538 {
   539 	CellArray *array;
   540 	HandleError err;
   541 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   542 
   543 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   544 		!= HandleError_None)
   545 	{
   546 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   547 	}
   548 
   549 	for (unsigned int i = 0; i < array->size(); i++)
   550 	{
   551 		if (params[2] == *array->at(i))
   552 		{
   553 			return (cell_t) i;
   554 		}
   555 	}
   556 
   557 	return -1;
   558 }
   559 
   560 REGISTER_NATIVES(cellArrayNatives)
   561 {
   562 	{"ClearArray",					ClearArray},
   563 	{"CreateArray",					CreateArray},
   564 	{"GetArrayArray",				GetArrayArray},
   565 	{"GetArrayCell",				GetArrayCell},
   566 	{"GetArraySize",				GetArraySize},
   567 	{"GetArrayString",				GetArrayString},
   568 	{"ResizeArray",					ResizeArray},
   569 	{"PushArrayArray",				PushArrayArray},
   570 	{"PushArrayCell",				PushArrayCell},
   571 	{"PushArrayString",				PushArrayString},
   572 	{"RemoveFromArray",				RemoveFromArray},
   573 	{"SetArrayCell",				SetArrayCell},
   574 	{"SetArrayString",				SetArrayString},
   575 	{"SetArrayArray",				SetArrayArray},
   576 	{"ShiftArrayUp",				ShiftArrayUp},
   577 	{"SwapArrayItems",				SwapArrayItems},
   578 	{"CloneArray",					CloneArray},
   579 	{"FindStringInArray",			FindStringInArray},
   580 	{"FindValueInArray",			FindValueInArray},
   581 	{NULL,							NULL},
   582 };