1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_adt_array.cpp Tue Jul 24 01:18:28 2007 +0000
1.3 @@ -0,0 +1,489 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * ===============================================================
1.7 + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.8 + * ===============================================================
1.9 + *
1.10 + * This file is not open source and may not be copied without explicit
1.11 + * written permission of AlliedModders LLC. This file may not be redistributed
1.12 + * in whole or significant part.
1.13 + * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
1.14 + *
1.15 + * Version: $Id$
1.16 + */
1.17 +
1.18 +#include <malloc.h>
1.19 +#include "sm_globals.h"
1.20 +#include "sm_stringutil.h"
1.21 +#include "CellArray.h"
1.22 +#include "HandleSys.h"
1.23 +
1.24 +HandleType_t htCellArray;
1.25 +
1.26 +class CellArrayHelpers :
1.27 + public SMGlobalClass,
1.28 + public IHandleTypeDispatch
1.29 +{
1.30 +public: //SMGlobalClass
1.31 + void OnSourceModAllInitialized()
1.32 + {
1.33 + htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.34 + }
1.35 + void OnSourceModShutdown()
1.36 + {
1.37 + g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
1.38 + }
1.39 +public: //IHandleTypeDispatch
1.40 + void OnHandleDestroy(HandleType_t type, void *object)
1.41 + {
1.42 + CellArray *array = (CellArray *)object;
1.43 + delete array;
1.44 + }
1.45 +} s_CellArrayHelpers;
1.46 +
1.47 +static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
1.48 +{
1.49 + if (!params[1])
1.50 + {
1.51 + return pContext->ThrowNativeError("Invalid block size (must be > 0)");
1.52 + }
1.53 +
1.54 + CellArray *array = new CellArray(params[1]);
1.55 +
1.56 + if (params[2])
1.57 + {
1.58 + array->resize(params[2]);
1.59 + }
1.60 +
1.61 + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.62 + if (!hndl)
1.63 + {
1.64 + delete array;
1.65 + }
1.66 +
1.67 + return hndl;
1.68 +}
1.69 +
1.70 +static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
1.71 +{
1.72 + CellArray *array;
1.73 + HandleError err;
1.74 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.75 +
1.76 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.77 + != HandleError_None)
1.78 + {
1.79 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.80 + }
1.81 +
1.82 + array->clear();
1.83 +
1.84 + return 1;
1.85 +}
1.86 +
1.87 +static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
1.88 +{
1.89 + CellArray *array;
1.90 + HandleError err;
1.91 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.92 +
1.93 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.94 + != HandleError_None)
1.95 + {
1.96 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.97 + }
1.98 +
1.99 + if (!array->resize(params[2]))
1.100 + {
1.101 + return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]);
1.102 + }
1.103 +
1.104 + return 1;
1.105 +}
1.106 +
1.107 +static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
1.108 +{
1.109 + CellArray *array;
1.110 + HandleError err;
1.111 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.112 +
1.113 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.114 + != HandleError_None)
1.115 + {
1.116 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.117 + }
1.118 +
1.119 + return (cell_t)array->size();
1.120 +}
1.121 +
1.122 +static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
1.123 +{
1.124 + CellArray *array;
1.125 + HandleError err;
1.126 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.127 +
1.128 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.129 + != HandleError_None)
1.130 + {
1.131 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.132 + }
1.133 +
1.134 + cell_t *blk = array->push();
1.135 + if (!blk)
1.136 + {
1.137 + return pContext->ThrowNativeError("Failed to grow array");
1.138 + }
1.139 +
1.140 + *blk = params[2];
1.141 +
1.142 + return (cell_t)(array->size() - 1);
1.143 +}
1.144 +
1.145 +static cell_t PushArrayString(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 + char *str;
1.164 + pContext->LocalToString(params[2], &str);
1.165 +
1.166 + strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
1.167 +
1.168 + return (cell_t)(array->size() - 1);
1.169 +}
1.170 +
1.171 +static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
1.172 +{
1.173 + CellArray *array;
1.174 + HandleError err;
1.175 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.176 +
1.177 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.178 + != HandleError_None)
1.179 + {
1.180 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.181 + }
1.182 +
1.183 + cell_t *blk = array->push();
1.184 + if (!blk)
1.185 + {
1.186 + return pContext->ThrowNativeError("Failed to grow array");
1.187 + }
1.188 +
1.189 + cell_t *addr;
1.190 + pContext->LocalToPhysAddr(params[2], &addr);
1.191 +
1.192 + size_t indexes = array->blocksize();
1.193 + if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
1.194 + {
1.195 + indexes = params[3];
1.196 + }
1.197 +
1.198 + memcpy(blk, addr, sizeof(cell_t) * indexes);
1.199 +
1.200 + return (cell_t)(array->size() - 1);
1.201 +}
1.202 +
1.203 +static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
1.204 +{
1.205 + CellArray *array;
1.206 + HandleError err;
1.207 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.208 +
1.209 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.210 + != HandleError_None)
1.211 + {
1.212 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.213 + }
1.214 +
1.215 + size_t idx = (size_t)params[2];
1.216 + if (idx >= array->size())
1.217 + {
1.218 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.219 + }
1.220 +
1.221 + cell_t *blk = array->at(idx);
1.222 +
1.223 + idx = (size_t)params[3];
1.224 + if (params[4] == 1)
1.225 + {
1.226 + if (idx >= array->blocksize())
1.227 + {
1.228 + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
1.229 + }
1.230 + return blk[idx];
1.231 + } else {
1.232 + if (idx >= array->blocksize() * 4)
1.233 + {
1.234 + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
1.235 + }
1.236 + return (cell_t)*((char *)blk + idx);
1.237 + }
1.238 +
1.239 + return 0;
1.240 +}
1.241 +
1.242 +static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
1.243 +{
1.244 + CellArray *array;
1.245 + HandleError err;
1.246 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.247 +
1.248 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.249 + != HandleError_None)
1.250 + {
1.251 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.252 + }
1.253 +
1.254 + size_t idx = (size_t)params[2];
1.255 + if (idx >= array->size())
1.256 + {
1.257 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.258 + }
1.259 +
1.260 + cell_t *blk = array->at(idx);
1.261 + size_t numWritten = 0;
1.262 +
1.263 + pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten);
1.264 +
1.265 + return numWritten;
1.266 +}
1.267 +
1.268 +static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
1.269 +{
1.270 + CellArray *array;
1.271 + HandleError err;
1.272 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.273 +
1.274 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.275 + != HandleError_None)
1.276 + {
1.277 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.278 + }
1.279 +
1.280 + size_t idx = (size_t)params[2];
1.281 + if (idx >= array->size())
1.282 + {
1.283 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.284 + }
1.285 +
1.286 + cell_t *blk = array->at(idx);
1.287 + size_t indexes = array->blocksize();
1.288 + if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
1.289 + {
1.290 + indexes = params[4];
1.291 + }
1.292 +
1.293 + cell_t *addr;
1.294 + pContext->LocalToPhysAddr(params[3], &addr);
1.295 +
1.296 + memcpy(addr, blk, sizeof(cell_t) * indexes);
1.297 +
1.298 + return indexes;
1.299 +}
1.300 +
1.301 +static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
1.302 +{
1.303 + CellArray *array;
1.304 + HandleError err;
1.305 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.306 +
1.307 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.308 + != HandleError_None)
1.309 + {
1.310 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.311 + }
1.312 +
1.313 + size_t idx = (size_t)params[2];
1.314 + if (idx >= array->size())
1.315 + {
1.316 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.317 + }
1.318 +
1.319 + cell_t *blk = array->at(idx);
1.320 +
1.321 + idx = (size_t)params[4];
1.322 + if (params[5] == 1)
1.323 + {
1.324 + if (idx >= array->blocksize())
1.325 + {
1.326 + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
1.327 + }
1.328 + blk[idx] = params[3];
1.329 + } else {
1.330 + if (idx >= array->blocksize() * 4)
1.331 + {
1.332 + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
1.333 + }
1.334 + *((char *)blk + idx) = (char)params[3];
1.335 + }
1.336 +
1.337 + return 1;
1.338 +}
1.339 +
1.340 +static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
1.341 +{
1.342 + CellArray *array;
1.343 + HandleError err;
1.344 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.345 +
1.346 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.347 + != HandleError_None)
1.348 + {
1.349 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.350 + }
1.351 +
1.352 + size_t idx = (size_t)params[2];
1.353 + if (idx >= array->size())
1.354 + {
1.355 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.356 + }
1.357 +
1.358 + cell_t *blk = array->at(idx);
1.359 +
1.360 + char *str;
1.361 + pContext->LocalToString(params[3], &str);
1.362 +
1.363 + return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
1.364 +}
1.365 +
1.366 +static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
1.367 +{
1.368 + CellArray *array;
1.369 + HandleError err;
1.370 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.371 +
1.372 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.373 + != HandleError_None)
1.374 + {
1.375 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.376 + }
1.377 +
1.378 + size_t idx = (size_t)params[2];
1.379 + if (idx >= array->size())
1.380 + {
1.381 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.382 + }
1.383 +
1.384 + cell_t *blk = array->at(idx);
1.385 + size_t indexes = array->blocksize();
1.386 + if (params[4] != -1 && (size_t)params[4] <= array->blocksize())
1.387 + {
1.388 + indexes = params[4];
1.389 + }
1.390 +
1.391 + cell_t *addr;
1.392 + pContext->LocalToPhysAddr(params[3], &addr);
1.393 +
1.394 + memcpy(blk, addr, sizeof(cell_t) * indexes);
1.395 +
1.396 + return indexes;
1.397 +}
1.398 +
1.399 +static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
1.400 +{
1.401 + CellArray *array;
1.402 + HandleError err;
1.403 + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1.404 +
1.405 + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
1.406 + != HandleError_None)
1.407 + {
1.408 + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
1.409 + }
1.410 +
1.411 + size_t idx = (size_t)params[2];
1.412 + if (idx >= array->size())
1.413 + {
1.414 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size());
1.415 + }
1.416 +
1.417 + array->insert_at(idx);
1.418 +
1.419 + return 1;
1.420 +}
1.421 +
1.422 +static cell_t RemoveFromArray(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->remove(idx);
1.441 +
1.442 + return 1;
1.443 +}
1.444 +
1.445 +static cell_t SwapArrayItems(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 idx1 = (size_t)params[2];
1.458 + size_t idx2 = (size_t)params[3];
1.459 + if (idx1 >= array->size())
1.460 + {
1.461 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size());
1.462 + }
1.463 + if (idx2 >= array->size())
1.464 + {
1.465 + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size());
1.466 + }
1.467 +
1.468 + array->swap(idx1, idx2);
1.469 +
1.470 + return 1;
1.471 +}
1.472 +
1.473 +REGISTER_NATIVES(cellArrayNatives)
1.474 +{
1.475 + {"ClearArray", ClearArray},
1.476 + {"CreateArray", CreateArray},
1.477 + {"GetArrayArray", GetArrayArray},
1.478 + {"GetArrayCell", GetArrayCell},
1.479 + {"GetArraySize", GetArraySize},
1.480 + {"GetArrayString", GetArrayString},
1.481 + {"ResizeArray", ResizeArray},
1.482 + {"PushArrayArray", PushArrayArray},
1.483 + {"PushArrayCell", PushArrayCell},
1.484 + {"PushArrayString", PushArrayString},
1.485 + {"RemoveFromArray", RemoveFromArray},
1.486 + {"SetArrayCell", SetArrayCell},
1.487 + {"SetArrayString", SetArrayString},
1.488 + {"SetArrayArray", SetArrayArray},
1.489 + {"ShiftArrayUp", ShiftArrayUp},
1.490 + {"SwapArrayItems", SwapArrayItems},
1.491 + {NULL, NULL},
1.492 +};