1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_adt_array.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,588 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include <malloc.h>
1.36 +#include "sm_globals.h"
1.37 +#include "sm_stringutil.h"
1.38 +#include "CellArray.h"
1.39 +#include "HandleSys.h"
1.40 +
1.41 +HandleType_t htCellArray;
1.42 +
1.43 +class CellArrayHelpers :
1.44 + public SMGlobalClass,
1.45 + public IHandleTypeDispatch
1.46 +{
1.47 +public: //SMGlobalClass
1.48 + void OnSourceModAllInitialized()
1.49 + {
1.50 + htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.51 + }
1.52 + void OnSourceModShutdown()
1.53 + {
1.54 + g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
1.55 + }
1.56 +public: //IHandleTypeDispatch
1.57 + void OnHandleDestroy(HandleType_t type, void *object)
1.58 + {
1.59 + CellArray *array = (CellArray *)object;
1.60 + delete array;
1.61 + }
1.62 + bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.63 + {
1.64 + CellArray *pArray = (CellArray *)object;
1.65 + *pSize = sizeof(CellArray) + pArray->mem_usage();
1.66 + return true;
1.67 + }
1.68 +} s_CellArrayHelpers;
1.69 +
1.70 +static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
1.71 +{
1.72 + if (!params[1])
1.73 + {
1.74 + return pContext->ThrowNativeError("Invalid block size (must be > 0)");
1.75 + }
1.76 +
1.77 + CellArray *array = new CellArray(params[1]);
1.78 +
1.79 + if (params[2])
1.80 + {
1.81 + array->resize(params[2]);
1.82 + }
1.83 +
1.84 + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.85 + if (!hndl)
1.86 + {
1.87 + delete array;
1.88 + }
1.89 +
1.90 + return hndl;
1.91 +}
1.92 +
1.93 +static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
1.94 +{
1.95 + CellArray *array;
1.96 + HandleError err;
1.97 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.98 +
1.99 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.100 + != HandleError_None)
1.101 + {
1.102 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.103 + }
1.104 +
1.105 + array->clear();
1.106 +
1.107 + return 1;
1.108 +}
1.109 +
1.110 +static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
1.111 +{
1.112 + CellArray *array;
1.113 + HandleError err;
1.114 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.115 +
1.116 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.117 + != HandleError_None)
1.118 + {
1.119 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.120 + }
1.121 +
1.122 + if (!array->resize(params[2]))
1.123 + {
1.124 + return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
1.125 + }
1.126 +
1.127 + return 1;
1.128 +}
1.129 +
1.130 +static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
1.131 +{
1.132 + CellArray *array;
1.133 + HandleError err;
1.134 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.135 +
1.136 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.137 + != HandleError_None)
1.138 + {
1.139 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.140 + }
1.141 +
1.142 + return (cell_t)array->size();
1.143 +}
1.144 +
1.145 +static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
1.146 +{
1.147 + CellArray *array;
1.148 + HandleError err;
1.149 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.150 +
1.151 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.152 + != HandleError_None)
1.153 + {
1.154 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.155 + }
1.156 +
1.157 + cell_t *blk = array->push();
1.158 + if (!blk)
1.159 + {
1.160 + return pContext->ThrowNativeError("Failed to grow array");
1.161 + }
1.162 +
1.163 + *blk = params[2];
1.164 +
1.165 + return (cell_t)(array->size() - 1);
1.166 +}
1.167 +
1.168 +static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
1.169 +{
1.170 + CellArray *array;
1.171 + HandleError err;
1.172 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.173 +
1.174 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.175 + != HandleError_None)
1.176 + {
1.177 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.178 + }
1.179 +
1.180 + cell_t *blk = array->push();
1.181 + if (!blk)
1.182 + {
1.183 + return pContext->ThrowNativeError("Failed to grow array");
1.184 + }
1.185 +
1.186 + char *str;
1.187 + pContext->LocalToString(params[2], &str);
1.188 +
1.189 + strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
1.190 +
1.191 + return (cell_t)(array->size() - 1);
1.192 +}
1.193 +
1.194 +static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
1.195 +{
1.196 + CellArray *array;
1.197 + HandleError err;
1.198 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.199 +
1.200 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.201 + != HandleError_None)
1.202 + {
1.203 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.204 + }
1.205 +
1.206 + cell_t *blk = array->push();
1.207 + if (!blk)
1.208 + {
1.209 + return pContext->ThrowNativeError("Failed to grow array");
1.210 + }
1.211 +
1.212 + cell_t *addr;
1.213 + pContext->LocalToPhysAddr(params[2], &addr);
1.214 +
1.215 + size_t indexes = array->blocksize();
1.216 + if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
1.217 + {
1.218 + indexes = params[3];
1.219 + }
1.220 +
1.221 + memcpy(blk, addr, sizeof(cell_t) * indexes);
1.222 +
1.223 + return (cell_t)(array->size() - 1);
1.224 +}
1.225 +
1.226 +static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
1.227 +{
1.228 + CellArray *array;
1.229 + HandleError err;
1.230 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.231 +
1.232 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.233 + != HandleError_None)
1.234 + {
1.235 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.236 + }
1.237 +
1.238 + size_t idx = (size_t)params[2];
1.239 + if (idx >= array->size())
1.240 + {
1.241 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.242 + }
1.243 +
1.244 + cell_t *blk = array->at(idx);
1.245 +
1.246 + idx = (size_t)params[3];
1.247 + if (params[4] == 0)
1.248 + {
1.249 + if (idx >= array->blocksize())
1.250 + {
1.251 + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
1.252 + }
1.253 + return blk[idx];
1.254 + } else {
1.255 + if (idx >= array->blocksize() * 4)
1.256 + {
1.257 + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
1.258 + }
1.259 + return (cell_t)*((char *)blk + idx);
1.260 + }
1.261 +
1.262 + return 0;
1.263 +}
1.264 +
1.265 +static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
1.266 +{
1.267 + CellArray *array;
1.268 + HandleError err;
1.269 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.270 +
1.271 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.272 + != HandleError_None)
1.273 + {
1.274 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.275 + }
1.276 +
1.277 + size_t idx = (size_t)params[2];
1.278 + if (idx >= array->size())
1.279 + {
1.280 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.281 + }
1.282 +
1.283 + cell_t *blk = array->at(idx);
1.284 + size_t numWritten = 0;
1.285 +
1.286 + pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
1.287 +
1.288 + return numWritten;
1.289 +}
1.290 +
1.291 +static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
1.292 +{
1.293 + CellArray *array;
1.294 + HandleError err;
1.295 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.296 +
1.297 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.298 + != HandleError_None)
1.299 + {
1.300 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.301 + }
1.302 +
1.303 + size_t idx = (size_t)params[2];
1.304 + if (idx >= array->size())
1.305 + {
1.306 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.307 + }
1.308 +
1.309 + cell_t *blk = array->at(idx);
1.310 + size_t indexes = array->blocksize();
1.311 + if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
1.312 + {
1.313 + indexes = params[4];
1.314 + }
1.315 +
1.316 + cell_t *addr;
1.317 + pContext->LocalToPhysAddr(params[3], &addr);
1.318 +
1.319 + memcpy(addr, blk, sizeof(cell_t) * indexes);
1.320 +
1.321 + return indexes;
1.322 +}
1.323 +
1.324 +static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
1.325 +{
1.326 + CellArray *array;
1.327 + HandleError err;
1.328 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.329 +
1.330 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.331 + != HandleError_None)
1.332 + {
1.333 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.334 + }
1.335 +
1.336 + size_t idx = (size_t)params[2];
1.337 + if (idx >= array->size())
1.338 + {
1.339 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.340 + }
1.341 +
1.342 + cell_t *blk = array->at(idx);
1.343 +
1.344 + idx = (size_t)params[4];
1.345 + if (params[5] == 0)
1.346 + {
1.347 + if (idx >= array->blocksize())
1.348 + {
1.349 + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
1.350 + }
1.351 + blk[idx] = params[3];
1.352 + } else {
1.353 + if (idx >= array->blocksize() * 4)
1.354 + {
1.355 + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
1.356 + }
1.357 + *((char *)blk + idx) = (char)params[3];
1.358 + }
1.359 +
1.360 + return 1;
1.361 +}
1.362 +
1.363 +static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
1.364 +{
1.365 + CellArray *array;
1.366 + HandleError err;
1.367 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.368 +
1.369 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.370 + != HandleError_None)
1.371 + {
1.372 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.373 + }
1.374 +
1.375 + size_t idx = (size_t)params[2];
1.376 + if (idx >= array->size())
1.377 + {
1.378 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.379 + }
1.380 +
1.381 + cell_t *blk = array->at(idx);
1.382 +
1.383 + char *str;
1.384 + pContext->LocalToString(params[3], &str);
1.385 +
1.386 + return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
1.387 +}
1.388 +
1.389 +static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
1.390 +{
1.391 + CellArray *array;
1.392 + HandleError err;
1.393 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.394 +
1.395 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.396 + != HandleError_None)
1.397 + {
1.398 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.399 + }
1.400 +
1.401 + size_t idx = (size_t)params[2];
1.402 + if (idx >= array->size())
1.403 + {
1.404 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.405 + }
1.406 +
1.407 + cell_t *blk = array->at(idx);
1.408 + size_t indexes = array->blocksize();
1.409 + if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
1.410 + {
1.411 + indexes = params[4];
1.412 + }
1.413 +
1.414 + cell_t *addr;
1.415 + pContext->LocalToPhysAddr(params[3], &addr);
1.416 +
1.417 + memcpy(blk, addr, sizeof(cell_t) * indexes);
1.418 +
1.419 + return indexes;
1.420 +}
1.421 +
1.422 +static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
1.423 +{
1.424 + CellArray *array;
1.425 + HandleError err;
1.426 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.427 +
1.428 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.429 + != HandleError_None)
1.430 + {
1.431 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.432 + }
1.433 +
1.434 + size_t idx = (size_t)params[2];
1.435 + if (idx >= array->size())
1.436 + {
1.437 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.438 + }
1.439 +
1.440 + array->insert_at(idx);
1.441 +
1.442 + return 1;
1.443 +}
1.444 +
1.445 +static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
1.446 +{
1.447 + CellArray *array;
1.448 + HandleError err;
1.449 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.450 +
1.451 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.452 + != HandleError_None)
1.453 + {
1.454 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.455 + }
1.456 +
1.457 + size_t idx = (size_t)params[2];
1.458 + if (idx >= array->size())
1.459 + {
1.460 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.461 + }
1.462 +
1.463 + array->remove(idx);
1.464 +
1.465 + return 1;
1.466 +}
1.467 +
1.468 +static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
1.469 +{
1.470 + CellArray *array;
1.471 + HandleError err;
1.472 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.473 +
1.474 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.475 + != HandleError_None)
1.476 + {
1.477 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.478 + }
1.479 +
1.480 + size_t idx1 = (size_t)params[2];
1.481 + size_t idx2 = (size_t)params[3];
1.482 + if (idx1 >= array->size())
1.483 + {
1.484 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
1.485 + }
1.486 + if (idx2 >= array->size())
1.487 + {
1.488 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
1.489 + }
1.490 +
1.491 + array->swap(idx1, idx2);
1.492 +
1.493 + return 1;
1.494 +}
1.495 +
1.496 +static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
1.497 +{
1.498 + CellArray *oldArray;
1.499 + HandleError err;
1.500 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.501 +
1.502 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
1.503 + != HandleError_None)
1.504 + {
1.505 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.506 + }
1.507 +
1.508 + CellArray *array = oldArray->clone();
1.509 +
1.510 + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.511 + if (!hndl)
1.512 + {
1.513 + delete array;
1.514 + }
1.515 +
1.516 + return hndl;
1.517 +}
1.518 +
1.519 +static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
1.520 +{
1.521 + CellArray *array;
1.522 + HandleError err;
1.523 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.524 +
1.525 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.526 + != HandleError_None)
1.527 + {
1.528 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.529 + }
1.530 +
1.531 + char *str;
1.532 + pContext->LocalToString(params[2], &str);
1.533 +
1.534 + for (unsigned int i = 0; i < array->size(); i++)
1.535 + {
1.536 + const char *array_str = (const char *)array->at(i);
1.537 + if (strcmp(str, array_str) == 0)
1.538 + {
1.539 + return (cell_t) i;
1.540 + }
1.541 + }
1.542 +
1.543 + return -1;
1.544 +}
1.545 +
1.546 +static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
1.547 +{
1.548 + CellArray *array;
1.549 + HandleError err;
1.550 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.551 +
1.552 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.553 + != HandleError_None)
1.554 + {
1.555 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.556 + }
1.557 +
1.558 + for (unsigned int i = 0; i < array->size(); i++)
1.559 + {
1.560 + if (params[2] == *array->at(i))
1.561 + {
1.562 + return (cell_t) i;
1.563 + }
1.564 + }
1.565 +
1.566 + return -1;
1.567 +}
1.568 +
1.569 +REGISTER_NATIVES(cellArrayNatives)
1.570 +{
1.571 + {"ClearArray", ClearArray},
1.572 + {"CreateArray", CreateArray},
1.573 + {"GetArrayArray", GetArrayArray},
1.574 + {"GetArrayCell", GetArrayCell},
1.575 + {"GetArraySize", GetArraySize},
1.576 + {"GetArrayString", GetArrayString},
1.577 + {"ResizeArray", ResizeArray},
1.578 + {"PushArrayArray", PushArrayArray},
1.579 + {"PushArrayCell", PushArrayCell},
1.580 + {"PushArrayString", PushArrayString},
1.581 + {"RemoveFromArray", RemoveFromArray},
1.582 + {"SetArrayCell", SetArrayCell},
1.583 + {"SetArrayString", SetArrayString},
1.584 + {"SetArrayArray", SetArrayArray},
1.585 + {"ShiftArrayUp", ShiftArrayUp},
1.586 + {"SwapArrayItems", SwapArrayItems},
1.587 + {"CloneArray", CloneArray},
1.588 + {"FindStringInArray", FindStringInArray},
1.589 + {"FindValueInArray", FindValueInArray},
1.590 + {NULL, NULL},
1.591 +};