diff -r 000000000000 -r b7aa2b626807 core/smn_adt_array.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/smn_adt_array.cpp Sun Mar 30 07:00:22 2008 +0000 @@ -0,0 +1,588 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include +#include "sm_globals.h" +#include "sm_stringutil.h" +#include "CellArray.h" +#include "HandleSys.h" + +HandleType_t htCellArray; + +class CellArrayHelpers : + public SMGlobalClass, + public IHandleTypeDispatch +{ +public: //SMGlobalClass + void OnSourceModAllInitialized() + { + htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL); + } + void OnSourceModShutdown() + { + g_HandleSys.RemoveType(htCellArray, g_pCoreIdent); + } +public: //IHandleTypeDispatch + void OnHandleDestroy(HandleType_t type, void *object) + { + CellArray *array = (CellArray *)object; + delete array; + } + bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize) + { + CellArray *pArray = (CellArray *)object; + *pSize = sizeof(CellArray) + pArray->mem_usage(); + return true; + } +} s_CellArrayHelpers; + +static cell_t CreateArray(IPluginContext *pContext, const cell_t *params) +{ + if (!params[1]) + { + return pContext->ThrowNativeError("Invalid block size (must be > 0)"); + } + + CellArray *array = new CellArray(params[1]); + + if (params[2]) + { + array->resize(params[2]); + } + + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL); + if (!hndl) + { + delete array; + } + + return hndl; +} + +static cell_t ClearArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + array->clear(); + + return 1; +} + +static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + if (!array->resize(params[2])) + { + return pContext->ThrowNativeError("Unable to resize array to \"%u\"", params[2]); + } + + return 1; +} + +static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + return (cell_t)array->size(); +} + +static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + *blk = params[2]; + + return (cell_t)(array->size() - 1); +} + +static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + char *str; + pContext->LocalToString(params[2], &str); + + strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t)); + + return (cell_t)(array->size() - 1); +} + +static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + cell_t *blk = array->push(); + if (!blk) + { + return pContext->ThrowNativeError("Failed to grow array"); + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[2], &addr); + + size_t indexes = array->blocksize(); + if (params[3] != -1 && (size_t)params[3] <= array->blocksize()) + { + indexes = params[3]; + } + + memcpy(blk, addr, sizeof(cell_t) * indexes); + + return (cell_t)(array->size() - 1); +} + +static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + idx = (size_t)params[3]; + if (params[4] == 0) + { + if (idx >= array->blocksize()) + { + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize()); + } + return blk[idx]; + } else { + if (idx >= array->blocksize() * 4) + { + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4); + } + return (cell_t)*((char *)blk + idx); + } + + return 0; +} + +static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t numWritten = 0; + + pContext->StringToLocalUTF8(params[3], params[4], (char *)blk, &numWritten); + + return numWritten; +} + +static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t indexes = array->blocksize(); + if (params[4] != -1 && (size_t)params[4] <= array->blocksize()) + { + indexes = params[4]; + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[3], &addr); + + memcpy(addr, blk, sizeof(cell_t) * indexes); + + return indexes; +} + +static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + idx = (size_t)params[4]; + if (params[5] == 0) + { + if (idx >= array->blocksize()) + { + return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize()); + } + blk[idx] = params[3]; + } else { + if (idx >= array->blocksize() * 4) + { + return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4); + } + *((char *)blk + idx) = (char)params[3]; + } + + return 1; +} + +static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + + char *str; + pContext->LocalToString(params[3], &str); + + return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t)); +} + +static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + cell_t *blk = array->at(idx); + size_t indexes = array->blocksize(); + if (params[4] != -1 && (size_t)params[4] <= array->blocksize()) + { + indexes = params[4]; + } + + cell_t *addr; + pContext->LocalToPhysAddr(params[3], &addr); + + memcpy(blk, addr, sizeof(cell_t) * indexes); + + return indexes; +} + +static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + array->insert_at(idx); + + return 1; +} + +static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx = (size_t)params[2]; + if (idx >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx, array->size()); + } + + array->remove(idx); + + return 1; +} + +static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + size_t idx1 = (size_t)params[2]; + size_t idx2 = (size_t)params[3]; + if (idx1 >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx1, array->size()); + } + if (idx2 >= array->size()) + { + return pContext->ThrowNativeError("Invalid index %d (count: %d)", idx2, array->size()); + } + + array->swap(idx1, idx2); + + return 1; +} + +static cell_t CloneArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *oldArray; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + CellArray *array = oldArray->clone(); + + Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL); + if (!hndl) + { + delete array; + } + + return hndl; +} + +static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + char *str; + pContext->LocalToString(params[2], &str); + + for (unsigned int i = 0; i < array->size(); i++) + { + const char *array_str = (const char *)array->at(i); + if (strcmp(str, array_str) == 0) + { + return (cell_t) i; + } + } + + return -1; +} + +static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params) +{ + CellArray *array; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err); + } + + for (unsigned int i = 0; i < array->size(); i++) + { + if (params[2] == *array->at(i)) + { + return (cell_t) i; + } + } + + return -1; +} + +REGISTER_NATIVES(cellArrayNatives) +{ + {"ClearArray", ClearArray}, + {"CreateArray", CreateArray}, + {"GetArrayArray", GetArrayArray}, + {"GetArrayCell", GetArrayCell}, + {"GetArraySize", GetArraySize}, + {"GetArrayString", GetArrayString}, + {"ResizeArray", ResizeArray}, + {"PushArrayArray", PushArrayArray}, + {"PushArrayCell", PushArrayCell}, + {"PushArrayString", PushArrayString}, + {"RemoveFromArray", RemoveFromArray}, + {"SetArrayCell", SetArrayCell}, + {"SetArrayString", SetArrayString}, + {"SetArrayArray", SetArrayArray}, + {"ShiftArrayUp", ShiftArrayUp}, + {"SwapArrayItems", SwapArrayItems}, + {"CloneArray", CloneArray}, + {"FindStringInArray", FindStringInArray}, + {"FindValueInArray", FindValueInArray}, + {NULL, NULL}, +};