3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
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.
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
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/>.
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>.
33 #include "common_logic.h"
34 #include "CellArray.h"
36 HandleType_t htCellArray;
38 class CellArrayHelpers :
40 public IHandleTypeDispatch
42 public: //SMGlobalClass
43 void OnSourceModAllInitialized()
45 htCellArray = handlesys->CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
47 void OnSourceModShutdown()
49 handlesys->RemoveType(htCellArray, g_pCoreIdent);
51 public: //IHandleTypeDispatch
52 void OnHandleDestroy(HandleType_t type, void *object)
54 CellArray *array = (CellArray *)object;
57 bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
59 CellArray *pArray = (CellArray *)object;
60 *pSize = sizeof(CellArray) + pArray->mem_usage();
65 static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
69 return pContext->ThrowNativeError("Invalid block size (must be > 0)");
72 CellArray *array = new CellArray(params[1]);
76 array->resize(params[2]);
79 Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
88 static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
92 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
94 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
97 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
105 static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
109 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
111 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
114 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
117 if (!array->resize(params[2]))
119 return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
125 static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
129 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
131 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
134 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
137 return (cell_t)array->size();
140 static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
144 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
146 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
149 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
152 cell_t *blk = array->push();
155 return pContext->ThrowNativeError("Failed to grow array");
160 return (cell_t)(array->size() - 1);
163 static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
167 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
169 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
172 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
175 cell_t *blk = array->push();
178 return pContext->ThrowNativeError("Failed to grow array");
182 pContext->LocalToString(params[2], &str);
184 smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
186 return (cell_t)(array->size() - 1);
189 static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
193 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
195 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
198 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
201 cell_t *blk = array->push();
204 return pContext->ThrowNativeError("Failed to grow array");
208 pContext->LocalToPhysAddr(params[2], &addr);
210 size_t indexes = array->blocksize();
211 if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
216 memcpy(blk, addr, sizeof(cell_t) * indexes);
218 return (cell_t)(array->size() - 1);
221 static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
225 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
227 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
230 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
233 size_t idx = (size_t)params[2];
234 if (idx >= array->size())
236 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
239 cell_t *blk = array->at(idx);
241 idx = (size_t)params[3];
244 if (idx >= array->blocksize())
246 return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
250 if (idx >= array->blocksize() * 4)
252 return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
254 return (cell_t)*((char *)blk + idx);
260 static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
264 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
266 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
269 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
272 size_t idx = (size_t)params[2];
273 if (idx >= array->size())
275 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
278 cell_t *blk = array->at(idx);
279 size_t numWritten = 0;
281 pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
286 static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
290 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
292 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
295 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
298 size_t idx = (size_t)params[2];
299 if (idx >= array->size())
301 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
304 cell_t *blk = array->at(idx);
305 size_t indexes = array->blocksize();
306 if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
312 pContext->LocalToPhysAddr(params[3], &addr);
314 memcpy(addr, blk, sizeof(cell_t) * indexes);
319 static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
323 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
325 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
328 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
331 size_t idx = (size_t)params[2];
332 if (idx >= array->size())
334 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
337 cell_t *blk = array->at(idx);
339 idx = (size_t)params[4];
342 if (idx >= array->blocksize())
344 return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
346 blk[idx] = params[3];
348 if (idx >= array->blocksize() * 4)
350 return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
352 *((char *)blk + idx) = (char)params[3];
358 static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
362 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
364 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
367 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
370 size_t idx = (size_t)params[2];
371 if (idx >= array->size())
373 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
376 cell_t *blk = array->at(idx);
379 pContext->LocalToString(params[3], &str);
381 return smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
384 static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
388 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
390 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
393 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
396 size_t idx = (size_t)params[2];
397 if (idx >= array->size())
399 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
402 cell_t *blk = array->at(idx);
403 size_t indexes = array->blocksize();
404 if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
410 pContext->LocalToPhysAddr(params[3], &addr);
412 memcpy(blk, addr, sizeof(cell_t) * indexes);
417 static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
421 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
423 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
426 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
429 size_t idx = (size_t)params[2];
430 if (idx >= array->size())
432 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
435 array->insert_at(idx);
440 static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
444 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
446 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
449 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
452 size_t idx = (size_t)params[2];
453 if (idx >= array->size())
455 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
463 static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
467 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
469 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
472 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
475 size_t idx1 = (size_t)params[2];
476 size_t idx2 = (size_t)params[3];
477 if (idx1 >= array->size())
479 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
481 if (idx2 >= array->size())
483 return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
486 array->swap(idx1, idx2);
491 static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
495 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
497 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
500 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
503 CellArray *array = oldArray->clone();
505 Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
514 static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
518 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
520 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
523 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
527 pContext->LocalToString(params[2], &str);
529 for (unsigned int i = 0; i < array->size(); i++)
531 const char *array_str = (const char *)array->at(i);
532 if (strcmp(str, array_str) == 0)
541 static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
545 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
547 if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
550 return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
553 for (unsigned int i = 0; i < array->size(); i++)
555 if (params[2] == *array->at(i))
564 REGISTER_NATIVES(cellArrayNatives)
566 {"ClearArray", ClearArray},
567 {"CreateArray", CreateArray},
568 {"GetArrayArray", GetArrayArray},
569 {"GetArrayCell", GetArrayCell},
570 {"GetArraySize", GetArraySize},
571 {"GetArrayString", GetArrayString},
572 {"ResizeArray", ResizeArray},
573 {"PushArrayArray", PushArrayArray},
574 {"PushArrayCell", PushArrayCell},
575 {"PushArrayString", PushArrayString},
576 {"RemoveFromArray", RemoveFromArray},
577 {"SetArrayCell", SetArrayCell},
578 {"SetArrayString", SetArrayString},
579 {"SetArrayArray", SetArrayArray},
580 {"ShiftArrayUp", ShiftArrayUp},
581 {"SwapArrayItems", SwapArrayItems},
582 {"CloneArray", CloneArray},
583 {"FindStringInArray", FindStringInArray},
584 {"FindValueInArray", FindValueInArray},