core/smn_adt_array.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jul 24 01:18:28 2007 +0000 (2007-07-24)
changeset 1156 a80f4ebe389f
child 1159 395c6ad644a1
permissions -rw-r--r--
initial import of adt array natives for amb576
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include <malloc.h>
    16 #include "sm_globals.h"
    17 #include "sm_stringutil.h"
    18 #include "CellArray.h"
    19 #include "HandleSys.h"
    20 
    21 HandleType_t htCellArray;
    22 
    23 class CellArrayHelpers : 
    24 	public SMGlobalClass,
    25 	public IHandleTypeDispatch
    26 {
    27 public: //SMGlobalClass
    28 	void OnSourceModAllInitialized()
    29 	{
    30 		htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    31 	}
    32 	void OnSourceModShutdown()
    33 	{
    34 		g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
    35 	}
    36 public: //IHandleTypeDispatch
    37 	void OnHandleDestroy(HandleType_t type, void *object)
    38 	{
    39 		CellArray *array = (CellArray *)object;
    40 		delete array;
    41 	}
    42 } s_CellArrayHelpers;
    43 
    44 static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
    45 {
    46 	if (!params[1])
    47 	{
    48 		return pContext->ThrowNativeError("Invalid block size (must be > 0)");
    49 	}
    50 
    51 	CellArray *array = new CellArray(params[1]);
    52 
    53 	if (params[2])
    54 	{
    55 		array->resize(params[2]);
    56 	}
    57 	
    58 	Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
    59 	if (!hndl)
    60 	{
    61 		delete array;
    62 	}
    63 
    64 	return hndl;
    65 }
    66 
    67 static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
    68 {
    69 	CellArray *array;
    70 	HandleError err;
    71 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
    72 
    73 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
    74 		!= HandleError_None)
    75 	{
    76 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
    77 	}
    78 
    79 	array->clear();
    80 	
    81 	return 1;
    82 }
    83 
    84 static cell_t ResizeArray(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 	if (!array->resize(params[2]))
    97 	{
    98 		return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
    99 	}
   100 
   101 	return 1;
   102 }
   103 
   104 static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
   105 {
   106 	CellArray *array;
   107 	HandleError err;
   108 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   109 
   110 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   111 		!= HandleError_None)
   112 	{
   113 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   114 	}
   115 
   116 	return (cell_t)array->size();
   117 }
   118 
   119 static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
   120 {
   121 	CellArray *array;
   122 	HandleError err;
   123 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   124 
   125 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   126 		!= HandleError_None)
   127 	{
   128 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   129 	}
   130 
   131 	cell_t *blk = array->push();
   132 	if (!blk)
   133 	{
   134 		return pContext->ThrowNativeError("Failed to grow array");
   135 	}
   136 
   137 	*blk = params[2];
   138 
   139 	return (cell_t)(array->size() - 1);
   140 }
   141 
   142 static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
   143 {
   144 	CellArray *array;
   145 	HandleError err;
   146 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   147 
   148 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   149 		!= HandleError_None)
   150 	{
   151 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   152 	}
   153 
   154 	cell_t *blk = array->push();
   155 	if (!blk)
   156 	{
   157 		return pContext->ThrowNativeError("Failed to grow array");
   158 	}
   159 
   160 	char *str;
   161 	pContext->LocalToString(params[2], &str);
   162 
   163 	strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   164 
   165 	return (cell_t)(array->size() - 1);
   166 }
   167 
   168 static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
   169 {
   170 	CellArray *array;
   171 	HandleError err;
   172 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   173 
   174 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   175 		!= HandleError_None)
   176 	{
   177 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   178 	}
   179 
   180 	cell_t *blk = array->push();
   181 	if (!blk)
   182 	{
   183 		return pContext->ThrowNativeError("Failed to grow array");
   184 	}
   185 
   186 	cell_t *addr;
   187 	pContext->LocalToPhysAddr(params[2], &addr);
   188 
   189 	size_t indexes = array->blocksize();
   190 	if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
   191 	{
   192 		indexes = params[3];
   193 	}
   194 
   195 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   196 
   197 	return (cell_t)(array->size() - 1);
   198 }
   199 
   200 static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
   201 {
   202 	CellArray *array;
   203 	HandleError err;
   204 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   205 
   206 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   207 		!= HandleError_None)
   208 	{
   209 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   210 	}
   211 
   212 	size_t idx = (size_t)params[2];
   213 	if (idx >= array->size())
   214 	{
   215 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   216 	}
   217 
   218 	cell_t *blk = array->at(idx);
   219 
   220 	idx = (size_t)params[3];
   221 	if (params[4] == 1)
   222 	{
   223 		if (idx >= array->blocksize())
   224 		{
   225 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   226 		}
   227 		return blk[idx];
   228 	} else {
   229 		if (idx >= array->blocksize() * 4)
   230 		{
   231 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   232 		}
   233 		return (cell_t)*((char *)blk + idx);
   234 	}
   235 
   236 	return 0;
   237 }
   238 
   239 static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
   240 {
   241 	CellArray *array;
   242 	HandleError err;
   243 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   244 
   245 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   246 		!= HandleError_None)
   247 	{
   248 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   249 	}
   250 
   251 	size_t idx = (size_t)params[2];
   252 	if (idx >= array->size())
   253 	{
   254 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   255 	}
   256 
   257 	cell_t *blk = array->at(idx);
   258 	size_t numWritten = 0;
   259 
   260 	pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
   261 
   262 	return numWritten;
   263 }
   264 
   265 static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
   266 {
   267 	CellArray *array;
   268 	HandleError err;
   269 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   270 
   271 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   272 		!= HandleError_None)
   273 	{
   274 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   275 	}
   276 
   277 	size_t idx = (size_t)params[2];
   278 	if (idx >= array->size())
   279 	{
   280 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   281 	}
   282 
   283 	cell_t *blk = array->at(idx);
   284 	size_t indexes = array->blocksize();
   285 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   286 	{
   287 		indexes = params[4];
   288 	}
   289 
   290 	cell_t *addr;
   291 	pContext->LocalToPhysAddr(params[3], &addr);
   292 
   293 	memcpy(addr, blk, sizeof(cell_t) * indexes);
   294 
   295 	return indexes;
   296 }
   297 
   298 static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
   299 {
   300 	CellArray *array;
   301 	HandleError err;
   302 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   303 
   304 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   305 		!= HandleError_None)
   306 	{
   307 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   308 	}
   309 
   310 	size_t idx = (size_t)params[2];
   311 	if (idx >= array->size())
   312 	{
   313 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   314 	}
   315 
   316 	cell_t *blk = array->at(idx);
   317 
   318 	idx = (size_t)params[4];
   319 	if (params[5] == 1)
   320 	{
   321 		if (idx >= array->blocksize())
   322 		{
   323 			return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
   324 		}
   325 		blk[idx] = params[3];
   326 	} else {
   327 		if (idx >= array->blocksize() * 4)
   328 		{
   329 			return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
   330 		}
   331 		*((char *)blk + idx) = (char)params[3];
   332 	}
   333 
   334 	return 1;
   335 }
   336 
   337 static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
   338 {
   339 	CellArray *array;
   340 	HandleError err;
   341 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   342 
   343 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   344 		!= HandleError_None)
   345 	{
   346 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   347 	}
   348 
   349 	size_t idx = (size_t)params[2];
   350 	if (idx >= array->size())
   351 	{
   352 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   353 	}
   354 
   355 	cell_t *blk = array->at(idx);
   356 
   357 	char *str;
   358 	pContext->LocalToString(params[3], &str);
   359 
   360 	return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
   361 }
   362 
   363 static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
   364 {
   365 	CellArray *array;
   366 	HandleError err;
   367 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   368 
   369 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   370 		!= HandleError_None)
   371 	{
   372 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   373 	}
   374 
   375 	size_t idx = (size_t)params[2];
   376 	if (idx >= array->size())
   377 	{
   378 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   379 	}
   380 
   381 	cell_t *blk = array->at(idx);
   382 	size_t indexes = array->blocksize();
   383 	if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
   384 	{
   385 		indexes = params[4];
   386 	}
   387 
   388 	cell_t *addr;
   389 	pContext->LocalToPhysAddr(params[3], &addr);
   390 
   391 	memcpy(blk, addr, sizeof(cell_t) * indexes);
   392 
   393 	return indexes;
   394 }
   395 
   396 static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
   397 {
   398 	CellArray *array;
   399 	HandleError err;
   400 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   401 
   402 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   403 		!= HandleError_None)
   404 	{
   405 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   406 	}
   407 
   408 	size_t idx = (size_t)params[2];
   409 	if (idx >= array->size())
   410 	{
   411 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   412 	}
   413 
   414 	array->insert_at(idx);
   415 
   416 	return 1;
   417 }
   418 
   419 static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
   420 {
   421 	CellArray *array;
   422 	HandleError err;
   423 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   424 
   425 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   426 		!= HandleError_None)
   427 	{
   428 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   429 	}
   430 
   431 	size_t idx = (size_t)params[2];
   432 	if (idx >= array->size())
   433 	{
   434 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
   435 	}
   436 
   437 	array->remove(idx);
   438 
   439 	return 1;
   440 }
   441 
   442 static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
   443 {
   444 	CellArray *array;
   445 	HandleError err;
   446 	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
   447 
   448 	if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) 
   449 		!= HandleError_None)
   450 	{
   451 		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
   452 	}
   453 
   454 	size_t idx1 = (size_t)params[2];
   455 	size_t idx2 = (size_t)params[3];
   456 	if (idx1 >= array->size())
   457 	{
   458 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
   459 	}
   460 	if (idx2 >= array->size())
   461 	{
   462 		return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
   463 	}
   464 
   465 	array->swap(idx1, idx2);
   466 
   467 	return 1;
   468 }
   469 
   470 REGISTER_NATIVES(cellArrayNatives)
   471 {
   472 	{"ClearArray",					ClearArray},
   473 	{"CreateArray",					CreateArray},
   474 	{"GetArrayArray",				GetArrayArray},
   475 	{"GetArrayCell",				GetArrayCell},
   476 	{"GetArraySize",				GetArraySize},
   477 	{"GetArrayString",				GetArrayString},
   478 	{"ResizeArray",					ResizeArray},
   479 	{"PushArrayArray",				PushArrayArray},
   480 	{"PushArrayCell",				PushArrayCell},
   481 	{"PushArrayString",				PushArrayString},
   482 	{"RemoveFromArray",				RemoveFromArray},
   483 	{"SetArrayCell",				SetArrayCell},
   484 	{"SetArrayString",				SetArrayString},
   485 	{"SetArrayArray",				SetArrayArray},
   486 	{"ShiftArrayUp",				ShiftArrayUp},
   487 	{"SwapArrayItems",				SwapArrayItems},
   488 	{NULL,							NULL},
   489 };