diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 2aa0efaf..5f3b3e36 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -649,7 +649,7 @@ static cell AMX_NATIVE_CALL show_dhudmessage(AMX *amx, cell *params) /* 2 param static cell AMX_NATIVE_CALL get_user_name(AMX *amx, cell *params) /* 3 param */ { int index = params[1]; - int maxlen = params[3] + 1; // EOS. + int maxlen = params[3]; if (index < 1 || index > gpGlobals->maxClients) return set_amxstring_utf8(amx, params[2], hostname->string, strlen(hostname->string), maxlen); @@ -1640,8 +1640,8 @@ static cell AMX_NATIVE_CALL get_concmd(AMX *amx, cell *params) /* 7 param */ if (cmd == 0) return 0; - set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3] + 1); // + EOS - set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6] + 1); // + EOS + set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3]); + set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6]); cell *cpFlags = get_amxaddr(amx, params[4]); *cpFlags = cmd->getFlags(); @@ -1677,8 +1677,8 @@ static cell AMX_NATIVE_CALL get_clcmd(AMX *amx, cell *params) /* 7 param */ if (cmd == 0) return 0; - set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3] + 1); // + EOS - set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6] + 1); // + EOS + set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3]); + set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6]); cell *cpFlags = get_amxaddr(amx, params[4]); *cpFlags = cmd->getFlags(); @@ -1692,8 +1692,8 @@ static cell AMX_NATIVE_CALL get_srvcmd(AMX *amx, cell *params) if (cmd == 0) return 0; - set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3] + 1); // + EOS - set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6] + 1); // + EOS + set_amxstring_utf8(amx, params[2], cmd->getCmdLine(), strlen(cmd->getCmdLine()), params[3]); + set_amxstring_utf8(amx, params[5], cmd->getCmdInfo(), strlen(cmd->getCmdInfo()), params[6]); cell *cpFlags = get_amxaddr(amx, params[4]); *cpFlags = cmd->getFlags(); @@ -2030,7 +2030,7 @@ static cell AMX_NATIVE_CALL format_time(AMX *amx, cell *params) /* 3 param */ char szDate[512]; ilen = strftime(szDate, 511, sptemp, lt); - return set_amxstring_utf8(amx, params[1], szDate, ilen, params[2] + 1); // + EOS + return set_amxstring_utf8(amx, params[1], szDate, ilen, params[2]); } @@ -2096,7 +2096,7 @@ static cell AMX_NATIVE_CALL read_data(AMX *amx, cell *params) /* 3 param */ return g_events.getArgInteger(params[1]); case 3: return set_amxstring_utf8(amx, params[2], g_events.getArgString(params[1]), - strlen(g_events.getArgString(params[1])),*get_amxaddr(amx, params[3]) + 1); // + EOS + strlen(g_events.getArgString(params[1])),*get_amxaddr(amx, params[3])); default: cell *fCell = get_amxaddr(amx, params[2]); REAL fparam = (REAL)g_events.getArgFloat(params[1]); @@ -2300,7 +2300,7 @@ static cell AMX_NATIVE_CALL get_localinfo(AMX *amx, cell *params) /* 3 param */ char* sptemp = get_amxstring(amx, params[1], 0, ilen); char *value = LOCALINFO(sptemp); - return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3]); } static cell AMX_NATIVE_CALL set_localinfo(AMX *amx, cell *params) /* 2 param */ @@ -2376,13 +2376,13 @@ static cell AMX_NATIVE_CALL read_argv(AMX *amx, cell *params) /* 3 param */ int argc = params[1]; const char *value = g_fakecmd.notify ? (argc >= 0 && argc < 3 ? g_fakecmd.argv[argc] : "") : CMD_ARGV(argc); - return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3]); } static cell AMX_NATIVE_CALL read_args(AMX *amx, cell *params) /* 2 param */ { const char* sValue = g_fakecmd.notify ? (g_fakecmd.argc > 1 ? g_fakecmd.args : g_fakecmd.argv[0]) : CMD_ARGS(); - return set_amxstring_utf8(amx, params[1], sValue ? sValue : "", sValue ? strlen(sValue) : 0, params[2] + 1); // +EOS + return set_amxstring_utf8(amx, params[1], sValue ? sValue : "", sValue ? strlen(sValue) : 0, params[2]); } static cell AMX_NATIVE_CALL get_user_msgid(AMX *amx, cell *params) /* 1 param */ @@ -2925,7 +2925,7 @@ static cell AMX_NATIVE_CALL force_unmodified(AMX *amx, cell *params) static cell AMX_NATIVE_CALL read_logdata(AMX *amx, cell *params) { const char *value = g_logevents.getLogString(); - return set_amxstring_utf8(amx, params[1], value, strlen(value), params[2] + 1); // + EOS + return set_amxstring_utf8(amx, params[1], value, strlen(value), params[2]); } static cell AMX_NATIVE_CALL read_logargc(AMX *amx, cell *params) @@ -2936,7 +2936,7 @@ static cell AMX_NATIVE_CALL read_logargc(AMX *amx, cell *params) static cell AMX_NATIVE_CALL read_logargv(AMX *amx, cell *params) { const char *value = g_logevents.getLogArg(params[1]); - return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3]); } static cell AMX_NATIVE_CALL parse_loguser(AMX *amx, cell *params) @@ -3224,9 +3224,9 @@ static cell AMX_NATIVE_CALL get_module(AMX *amx, cell *params) const char *author = info && info->author ? info->author : "unk"; const char *version = info && info->version ? info->version : "unk"; - set_amxstring_utf8(amx, params[2], name, strlen(name), params[3] + 1); // + EOS - set_amxstring_utf8(amx, params[4], author, strlen(author), params[5] + 1); // + EOS - set_amxstring_utf8(amx, params[6], version, strlen(version), params[7] + 1); // + EOS + set_amxstring_utf8(amx, params[2], name, strlen(name), params[3]); + set_amxstring_utf8(amx, params[4], author, strlen(author), params[5]); + set_amxstring_utf8(amx, params[6], version, strlen(version), params[7]); } // compatibility problem possible diff --git a/amxmodx/cvars.cpp b/amxmodx/cvars.cpp index 21db4793..9c497065 100644 --- a/amxmodx/cvars.cpp +++ b/amxmodx/cvars.cpp @@ -207,7 +207,7 @@ static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params) const char *value = info ? info->var->string : ""; length = info ? strlen(value) : 0; - return set_amxstring_utf8(amx, params[2], value, length, params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], value, length, params[3]); } // set_cvar_flags(const cvar[], flags) @@ -336,7 +336,7 @@ static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params) return 0; } - return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3] + 1); // EOS + return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3]); } // get_pcvar_bounds(pcvar, CvarBounds:type, &Float:value) diff --git a/amxmodx/datapacks.cpp b/amxmodx/datapacks.cpp index 7da0c0ff..43e619f7 100644 --- a/amxmodx/datapacks.cpp +++ b/amxmodx/datapacks.cpp @@ -143,7 +143,7 @@ static cell AMX_NATIVE_CALL ReadPackString(AMX* amx, cell* params) size_t len; const char *str = d->ReadString(&len); - return set_amxstring_utf8(amx, params[2], str, len, params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], str, len, params[3]); } static cell AMX_NATIVE_CALL ResetPack(AMX* amx, cell* params) diff --git a/amxmodx/datastructs.cpp b/amxmodx/datastructs.cpp index 0dd59fb0..5f5337fd 100644 --- a/amxmodx/datastructs.cpp +++ b/amxmodx/datastructs.cpp @@ -1,944 +1,944 @@ -// vim: set ts=4 sw=4 tw=99 noet: -// -// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). -// Copyright (C) The AMX Mod X Development Team. -// -// This software is licensed under the GNU General Public License, version 3 or higher. -// Additional exceptions apply. For full license details, see LICENSE.txt or visit: -// https://alliedmods.net/amxmodx-license - -#include "amxmodx.h" -#include "datastructs.h" -#include - -// Note: All handles start at 1. 0 and below are invalid handles. -// This way, a plugin that doesn't initialize a vector or -// string will not be able to modify another plugin's data -// on accident. -ke::Vector VectorHolder; - - -// Array:ArrayCreate(cellsize=1, reserved=32); -static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params) -{ - // params[1] (cellsize) is how big in cells each element is. - // this MUST be greater than 0! - int cellsize = params[1]; - - // params[2] (reserved) is how many elements to allocate - // immediately when the list is created. - int reserved = params[2]; - - if (cellsize <= 0) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize); - return -1; - } - - if (reserved < 0) - { - reserved = 0; - } - - // Scan through the vector list to see if any are NULL. - // NULL means the vector was previously destroyed. - for (unsigned int i=0; i < VectorHolder.length(); ++i) - { - if (VectorHolder[i]==NULL) - { - VectorHolder[i] = new CellArray(cellsize, reserved); - return i + 1; - } - } - - // None are NULL, create a new vector - CellArray* NewVector = new CellArray(cellsize, reserved); - - VectorHolder.append(NewVector); - - return VectorHolder.length(); -} - -// native ArrayClear(Array:which); -static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - vec->clear(); - - return 1; -} - -// native ArraySize(Array:which); -static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - return vec->size(); -} - -// native bool:ArrayResize(Array:which, newsize); -static cell AMX_NATIVE_CALL ArrayResize(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - if (!vec->resize(params[2])) - { - LogError(amx, AMX_ERR_NATIVE, "Unable to resize array to \"%u\"", params[2]); - return 0; - } - - return 1; -} - -// native Array:ArrayClone(Array:which); -static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - CellArray *clonevec = vec->clone(); - - // Scan through the vector list to see if any are NULL. - // NULL means the vector was previously destroyed. - for (unsigned int i = 0; i < VectorHolder.length(); ++i) - { - if (VectorHolder[i] == NULL) - { - VectorHolder[i] = clonevec; - return i + 1; - } - } - - VectorHolder.append(clonevec); - - return VectorHolder.length(); -} - -// native ArrayGetArray(Array:which, item, any:output[], size = -1); -static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - size_t indexes = vec->blocksize(); - - if (*params / sizeof(cell) == 4) - { - if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) - { - indexes = params[4]; - } - } - - cell *addr = get_amxaddr(amx, params[3]); - - memcpy(addr, blk, sizeof(cell) * indexes); - - return indexes; -} - -// native any:ArrayGetCell(Array:which, item, block = 0, bool:asChar = false); -static cell AMX_NATIVE_CALL ArrayGetCell(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - - if (*params / sizeof(cell) <= 2) - { - return *blk; - } - - idx = (size_t)params[3]; - - if (!params[4]) - { - if (idx >= vec->blocksize()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize()); - return 0; - } - - return blk[idx]; - } - else - { - if (idx >= vec->blocksize() * 4) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4); - return 0; - } - - return (cell)*((char *)blk + idx); - } - - return 0; -} - -// native ArrayGetString(Array:which, item, output[], size); -static cell AMX_NATIVE_CALL ArrayGetString(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - return set_amxstring_utf8(amx, params[3], blk, amxstring_len(blk), params[4] + 1); // + EOS. -} - -// native ArraySetArray(Array:which, item, const any:input[], size =-1); -static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - size_t indexes = vec->blocksize(); - - if (*params / sizeof(cell) == 4) - { - if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) - { - indexes = params[4]; - } - } - - cell *addr = get_amxaddr(amx, params[3]); - - memcpy(blk, addr, sizeof(cell) * indexes); - - return indexes; -} - -// native ArraySetCell(Array:which, item, any:input, block = 0, bool:asChar = false); -static cell AMX_NATIVE_CALL ArraySetCell(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - idx = (size_t)params[4]; - - if (*params / sizeof(cell) <= 3) - { - *blk = params[3]; - return 1; - } - - if (params[5] == 0) - { - if (idx >= vec->blocksize()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize()); - return 0; - } - blk[idx] = params[3]; - } - else - { - if (idx >= vec->blocksize() * 4) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4); - return 0; - } - *((char *)blk + idx) = (char)params[3]; - } - - return 1; -} - -// native ArraySetString(Array:which, item, const input[]); -static cell AMX_NATIVE_CALL ArraySetString(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell *blk = vec->at(idx); - - int len; - char *str = get_amxstring(amx, params[3], 0, len); - - return strncopy(blk, str, ke::Min((size_t)len + 1, vec->blocksize())); -} - -// native ArrayPushArray(Array:which, const any:input[], size = -1); -static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - cell *blk = vec->push(); - - if (!blk) - { - LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); - return 0; - } - - cell *addr = get_amxaddr(amx, params[2]); - size_t indexes = vec->blocksize(); - - if (*params / sizeof(cell) == 3) - { - if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) - { - indexes = params[3]; - } - } - - memcpy(blk, addr, sizeof(cell) * indexes); - - return static_cast((vec->size() - 1)); -} - -// native ArrayPushCell(Array:which, any:input); -static cell AMX_NATIVE_CALL ArrayPushCell(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - cell *blk = vec->push(); - - if (!blk) - { - LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); - return 0; - } - - *blk = params[2]; - - return static_cast((vec->size() - 1)); -} - -// native ArrayPushString(Array:which, const input[]); -static cell AMX_NATIVE_CALL ArrayPushString(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - cell *blk = vec->push(); - if (!blk) - { - LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); - return 0; - } - - strncopy(blk, get_amxaddr(amx, params[2]), vec->blocksize()); - - return static_cast((vec->size() - 1)); -} - -// native DoNotUse : ArrayGetStringHandle(Array : which, item); -static cell AMX_NATIVE_CALL ArrayGetStringHandle(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - cell* ptr = vec->at(idx); - - if (ptr == NULL) - { - return 0; - } - - return reinterpret_cast(ptr); -} - -// native ArrayInsertArrayAfter(Array:which, item, const any:input[]); -static cell AMX_NATIVE_CALL ArrayInsertArrayAfter(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2] + 1; - - if (idx > vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayAfter (%d:%d)", idx, vec->size()); - return 0; - } - - cell *addr = get_amxaddr(amx, params[3]); - - memcpy(vec->insert_at(idx), addr, sizeof(cell) * vec->blocksize()); - - return 1; -} - -// native ArrayInsertCellAfter(Array:which, item, any:input); -static cell AMX_NATIVE_CALL ArrayInsertCellAfter(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2] + 1; - - if (idx > vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellAfter (%d:%d)", idx, vec->size()); - return 0; - } - - *vec->insert_at(idx) = params[3]; - - return 1; -} - -// native ArrayInsertStringAfter(Array:which, item, const input[]); -static cell AMX_NATIVE_CALL ArrayInsertStringAfter(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2] + 1; - - if (idx > vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringAfter (%d:%d)", idx, vec->size()); - return 0; - } - - int len; - const char *str = get_amxstring(amx, params[3], 0, len); - - return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize())); -} - -// native ArrayInsertArrayBefore(Array:which, item, const any:input[]); -static cell AMX_NATIVE_CALL ArrayInsertArrayBefore(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", idx, vec->size()); - return 0; - } - - cell *addr = get_amxaddr(amx, params[3]); - - memcpy(vec->insert_at(idx), addr, vec->blocksize() * sizeof(cell)); - - return 1; -} - -// native ArrayInsertCellBefore(Array:which, item, const any:input); -static cell AMX_NATIVE_CALL ArrayInsertCellBefore(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", idx, vec->size()); - return 0; - } - - *vec->insert_at(idx) = params[3]; - - return 1; -} -// native ArrayInsertStringBefore(Array:which, item, const input[]); -static cell AMX_NATIVE_CALL ArrayInsertStringBefore(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", idx, vec->size()); - return 0; - } - - int len; - const char *str = get_amxstring(amx, params[3], 0, len); - - return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize())); -} - -// native ArraySwap(Array:which, item1, item2); -static cell AMX_NATIVE_CALL ArraySwap(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx1 = (size_t)params[2]; - size_t idx2 = (size_t)params[3]; - - if (idx1 >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx1, vec->size()); - return 0; - } - - if (idx2 >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx2, vec->size()); - return 0; - } - - vec->swap(idx1, idx2); - - return 1; -} - -// native ArrayDeleteItem(Array:which, item); -static cell AMX_NATIVE_CALL ArrayDeleteItem(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return 0; - } - - size_t idx = (size_t)params[2]; - - if (idx >= vec->size()) - { - LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); - return 0; - } - - vec->remove(idx); - - return 1; -} - -// native ArrayDestroy(&Array:which); -static cell AMX_NATIVE_CALL ArrayDestroy(AMX* amx, cell* params) -{ - cell* handle = get_amxaddr(amx, params[1]); - - if (*handle == 0) - { - return 0; - } - - CellArray* vec = HandleToVector(amx, *handle); - - if (vec == NULL) - { - return 0; - } - - delete vec; - - VectorHolder[*handle-1] = NULL; - - *handle = 0; - - return 1; -} - - -struct ArraySort_s -{ - int func; - cell array_hndl; - cell* array_base; - cell array_bsize; - cell data; - cell size; - cell addr1; - cell addr2; - AMX *amx; -}; - -ArraySort_s SortInfo; - -int SortArrayList(const void *elem1, const void *elem2) -{ - return executeForwards( - SortInfo.func, - SortInfo.array_hndl, - ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize, - ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize, - SortInfo.data, - SortInfo.size - ); -} - -// native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0); -static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params) -{ - int handle = params[1]; - CellArray* vec = HandleToVector(amx, handle); - - if (vec == NULL) - { - return 0; - } - - int len; - char* funcName = get_amxstring(amx, params[2], 0, len); - - // MySortFunc(Array:array, item1, item2, const data[], data_size) - int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); - if (func < 0) - { - LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); - return 0; - } - - size_t arraysize = vec->size(); - size_t blocksize = vec->blocksize(); - cell *array = vec->base(); - - ArraySort_s oldinfo = SortInfo; - - SortInfo.func = func; - SortInfo.array_base = array; - SortInfo.array_bsize = static_cast(blocksize); - SortInfo.array_hndl = handle; - SortInfo.data = params[3]; - SortInfo.size = params[4]; - - qsort(array, arraysize, blocksize * sizeof(cell), SortArrayList); - - SortInfo = oldinfo; - - unregisterSPForward(func); - - return 1; -} - - -int SortArrayListExCell(const void *elem1, const void *elem2) -{ - size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize; - size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize; - - return executeForwards( - SortInfo.func, - SortInfo.array_hndl, - *&SortInfo.array_base[index1 * SortInfo.array_bsize], - *&SortInfo.array_base[index2 * SortInfo.array_bsize], - SortInfo.data, - SortInfo.size - ); -} - -int SortArrayListExArray(const void *elem1, const void *elem2) -{ - size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize; - size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize; - - cell *addr1 = get_amxaddr(SortInfo.amx, SortInfo.addr1); - cell *addr2 = get_amxaddr(SortInfo.amx, SortInfo.addr2); - - memcpy(addr1, &SortInfo.array_base[index1 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell)); - memcpy(addr2, &SortInfo.array_base[index2 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell)); - - return executeForwards( - SortInfo.func, - SortInfo.array_hndl, - SortInfo.addr1, - SortInfo.addr2, - SortInfo.data, - SortInfo.size - ); -} - -// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0); -static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params) -{ - int handle = params[1]; - CellArray* vec = HandleToVector(amx, handle); - - if (vec == NULL) - { - return 0; - } - - int len; - char* funcName = get_amxstring(amx, params[2], 0, len); - - int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); - - if (!func) - { - LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); - return 0; - } - - size_t arraysize = vec->size(); - size_t blocksize = vec->blocksize(); - cell *array = vec->base(); - cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL; - - if (blocksize > 1) - { - int err; - if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE - || ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE) - { - LogError(amx, err, "Ran out of memory"); - return 0; - } - } - - ArraySort_s oldinfo = SortInfo; - - SortInfo.func = func; - SortInfo.array_base = array; - SortInfo.array_bsize = static_cast(blocksize); - SortInfo.array_hndl = params[1]; - SortInfo.data = params[3]; - SortInfo.size = params[4]; - SortInfo.amx = amx; - SortInfo.addr1 = amx_addr1; - SortInfo.addr2 = amx_addr2; - - qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell); - - SortInfo = oldinfo; - - if (blocksize > 1) - { - amx_Release(amx, amx_addr1); - amx_Release(amx, amx_addr2); - } - - unregisterSPForward(func); - - return 1; -} - -extern bool fastcellcmp(cell *a, cell *b, cell len); -extern int amxstring_len(cell* a); - -// native ArrayFindString(Array:which, const item[]); -static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return -1; - } - - cell *b, *a = get_amxaddr(amx, params[2]); - size_t cellcount = vec->blocksize(); - size_t a_len = ke::Max(1, amxstring_len(a)); - size_t len = a_len > cellcount ? cellcount : a_len; - - for (size_t i = 0; i < vec->size(); i++) - { - b = vec->at(i); - - if (fastcellcmp(a, b, len)) - { - return static_cast(i); - } - } - - return -1; -} - -// native ArrayFindValue(Array:which, any:item); -static cell AMX_NATIVE_CALL ArrayFindValue(AMX* amx, cell* params) -{ - CellArray* vec = HandleToVector(amx, params[1]); - - if (vec == NULL) - { - return -1; - } - - for (size_t i = 0; i < vec->size(); i++) - { - if (params[2] == *vec->at(i)) - { - return static_cast(i); - } - } - - return -1; -} - -AMX_NATIVE_INFO g_DataStructNatives[] = -{ - { "ArrayCreate", ArrayCreate }, - { "ArrayClear", ArrayClear }, - { "ArrayClone", ArrayClone }, - { "ArraySize", ArraySize }, - { "ArrayResize", ArrayResize }, - { "ArrayGetArray", ArrayGetArray }, - { "ArrayGetCell", ArrayGetCell }, - { "ArrayGetString", ArrayGetString }, - { "ArraySetArray", ArraySetArray }, - { "ArraySetCell", ArraySetCell }, - { "ArraySetString", ArraySetString }, - { "ArrayPushArray", ArrayPushArray }, - { "ArrayPushCell", ArrayPushCell }, - { "ArrayPushString", ArrayPushString }, - { "ArrayInsertArrayAfter", ArrayInsertArrayAfter }, - { "ArrayInsertCellAfter", ArrayInsertCellAfter }, - { "ArrayInsertStringAfter", ArrayInsertStringAfter }, - { "ArrayInsertArrayBefore", ArrayInsertArrayBefore }, - { "ArrayInsertCellBefore", ArrayInsertCellBefore }, - { "ArrayInsertStringBefore", ArrayInsertStringBefore }, - { "ArraySwap", ArraySwap }, - { "ArrayDeleteItem", ArrayDeleteItem }, - { "ArrayGetStringHandle", ArrayGetStringHandle }, - { "ArrayDestroy", ArrayDestroy }, - { "ArraySort", ArraySort }, - { "ArraySortEx", ArraySortEx }, - { "ArrayFindString", ArrayFindString }, - { "ArrayFindValue", ArrayFindValue }, - - { NULL, NULL } -}; +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#include "amxmodx.h" +#include "datastructs.h" +#include + +// Note: All handles start at 1. 0 and below are invalid handles. +// This way, a plugin that doesn't initialize a vector or +// string will not be able to modify another plugin's data +// on accident. +ke::Vector VectorHolder; + + +// Array:ArrayCreate(cellsize=1, reserved=32); +static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params) +{ + // params[1] (cellsize) is how big in cells each element is. + // this MUST be greater than 0! + int cellsize = params[1]; + + // params[2] (reserved) is how many elements to allocate + // immediately when the list is created. + int reserved = params[2]; + + if (cellsize <= 0) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize); + return -1; + } + + if (reserved < 0) + { + reserved = 0; + } + + // Scan through the vector list to see if any are NULL. + // NULL means the vector was previously destroyed. + for (unsigned int i=0; i < VectorHolder.length(); ++i) + { + if (VectorHolder[i]==NULL) + { + VectorHolder[i] = new CellArray(cellsize, reserved); + return i + 1; + } + } + + // None are NULL, create a new vector + CellArray* NewVector = new CellArray(cellsize, reserved); + + VectorHolder.append(NewVector); + + return VectorHolder.length(); +} + +// native ArrayClear(Array:which); +static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + vec->clear(); + + return 1; +} + +// native ArraySize(Array:which); +static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + return vec->size(); +} + +// native bool:ArrayResize(Array:which, newsize); +static cell AMX_NATIVE_CALL ArrayResize(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + if (!vec->resize(params[2])) + { + LogError(amx, AMX_ERR_NATIVE, "Unable to resize array to \"%u\"", params[2]); + return 0; + } + + return 1; +} + +// native Array:ArrayClone(Array:which); +static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + CellArray *clonevec = vec->clone(); + + // Scan through the vector list to see if any are NULL. + // NULL means the vector was previously destroyed. + for (unsigned int i = 0; i < VectorHolder.length(); ++i) + { + if (VectorHolder[i] == NULL) + { + VectorHolder[i] = clonevec; + return i + 1; + } + } + + VectorHolder.append(clonevec); + + return VectorHolder.length(); +} + +// native ArrayGetArray(Array:which, item, any:output[], size = -1); +static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + size_t indexes = vec->blocksize(); + + if (*params / sizeof(cell) == 4) + { + if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) + { + indexes = params[4]; + } + } + + cell *addr = get_amxaddr(amx, params[3]); + + memcpy(addr, blk, sizeof(cell) * indexes); + + return indexes; +} + +// native any:ArrayGetCell(Array:which, item, block = 0, bool:asChar = false); +static cell AMX_NATIVE_CALL ArrayGetCell(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + + if (*params / sizeof(cell) <= 2) + { + return *blk; + } + + idx = (size_t)params[3]; + + if (!params[4]) + { + if (idx >= vec->blocksize()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize()); + return 0; + } + + return blk[idx]; + } + else + { + if (idx >= vec->blocksize() * 4) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4); + return 0; + } + + return (cell)*((char *)blk + idx); + } + + return 0; +} + +// native ArrayGetString(Array:which, item, output[], size); +static cell AMX_NATIVE_CALL ArrayGetString(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + return set_amxstring_utf8(amx, params[3], blk, amxstring_len(blk), params[4]); +} + +// native ArraySetArray(Array:which, item, const any:input[], size =-1); +static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + size_t indexes = vec->blocksize(); + + if (*params / sizeof(cell) == 4) + { + if (params[4] != -1 && (size_t)params[4] <= vec->blocksize()) + { + indexes = params[4]; + } + } + + cell *addr = get_amxaddr(amx, params[3]); + + memcpy(blk, addr, sizeof(cell) * indexes); + + return indexes; +} + +// native ArraySetCell(Array:which, item, any:input, block = 0, bool:asChar = false); +static cell AMX_NATIVE_CALL ArraySetCell(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + idx = (size_t)params[4]; + + if (*params / sizeof(cell) <= 3) + { + *blk = params[3]; + return 1; + } + + if (params[5] == 0) + { + if (idx >= vec->blocksize()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize()); + return 0; + } + blk[idx] = params[3]; + } + else + { + if (idx >= vec->blocksize() * 4) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4); + return 0; + } + *((char *)blk + idx) = (char)params[3]; + } + + return 1; +} + +// native ArraySetString(Array:which, item, const input[]); +static cell AMX_NATIVE_CALL ArraySetString(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell *blk = vec->at(idx); + + int len; + char *str = get_amxstring(amx, params[3], 0, len); + + return strncopy(blk, str, ke::Min((size_t)len + 1, vec->blocksize())); +} + +// native ArrayPushArray(Array:which, const any:input[], size = -1); +static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + cell *blk = vec->push(); + + if (!blk) + { + LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); + return 0; + } + + cell *addr = get_amxaddr(amx, params[2]); + size_t indexes = vec->blocksize(); + + if (*params / sizeof(cell) == 3) + { + if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) + { + indexes = params[3]; + } + } + + memcpy(blk, addr, sizeof(cell) * indexes); + + return static_cast((vec->size() - 1)); +} + +// native ArrayPushCell(Array:which, any:input); +static cell AMX_NATIVE_CALL ArrayPushCell(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + cell *blk = vec->push(); + + if (!blk) + { + LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); + return 0; + } + + *blk = params[2]; + + return static_cast((vec->size() - 1)); +} + +// native ArrayPushString(Array:which, const input[]); +static cell AMX_NATIVE_CALL ArrayPushString(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + cell *blk = vec->push(); + if (!blk) + { + LogError(amx, AMX_ERR_NATIVE, "Failed to grow array"); + return 0; + } + + strncopy(blk, get_amxaddr(amx, params[2]), vec->blocksize()); + + return static_cast((vec->size() - 1)); +} + +// native DoNotUse : ArrayGetStringHandle(Array : which, item); +static cell AMX_NATIVE_CALL ArrayGetStringHandle(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + cell* ptr = vec->at(idx); + + if (ptr == NULL) + { + return 0; + } + + return reinterpret_cast(ptr); +} + +// native ArrayInsertArrayAfter(Array:which, item, const any:input[]); +static cell AMX_NATIVE_CALL ArrayInsertArrayAfter(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2] + 1; + + if (idx > vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayAfter (%d:%d)", idx, vec->size()); + return 0; + } + + cell *addr = get_amxaddr(amx, params[3]); + + memcpy(vec->insert_at(idx), addr, sizeof(cell) * vec->blocksize()); + + return 1; +} + +// native ArrayInsertCellAfter(Array:which, item, any:input); +static cell AMX_NATIVE_CALL ArrayInsertCellAfter(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2] + 1; + + if (idx > vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellAfter (%d:%d)", idx, vec->size()); + return 0; + } + + *vec->insert_at(idx) = params[3]; + + return 1; +} + +// native ArrayInsertStringAfter(Array:which, item, const input[]); +static cell AMX_NATIVE_CALL ArrayInsertStringAfter(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2] + 1; + + if (idx > vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringAfter (%d:%d)", idx, vec->size()); + return 0; + } + + int len; + const char *str = get_amxstring(amx, params[3], 0, len); + + return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize())); +} + +// native ArrayInsertArrayBefore(Array:which, item, const any:input[]); +static cell AMX_NATIVE_CALL ArrayInsertArrayBefore(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", idx, vec->size()); + return 0; + } + + cell *addr = get_amxaddr(amx, params[3]); + + memcpy(vec->insert_at(idx), addr, vec->blocksize() * sizeof(cell)); + + return 1; +} + +// native ArrayInsertCellBefore(Array:which, item, const any:input); +static cell AMX_NATIVE_CALL ArrayInsertCellBefore(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", idx, vec->size()); + return 0; + } + + *vec->insert_at(idx) = params[3]; + + return 1; +} +// native ArrayInsertStringBefore(Array:which, item, const input[]); +static cell AMX_NATIVE_CALL ArrayInsertStringBefore(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", idx, vec->size()); + return 0; + } + + int len; + const char *str = get_amxstring(amx, params[3], 0, len); + + return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize())); +} + +// native ArraySwap(Array:which, item1, item2); +static cell AMX_NATIVE_CALL ArraySwap(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx1 = (size_t)params[2]; + size_t idx2 = (size_t)params[3]; + + if (idx1 >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx1, vec->size()); + return 0; + } + + if (idx2 >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx2, vec->size()); + return 0; + } + + vec->swap(idx1, idx2); + + return 1; +} + +// native ArrayDeleteItem(Array:which, item); +static cell AMX_NATIVE_CALL ArrayDeleteItem(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return 0; + } + + size_t idx = (size_t)params[2]; + + if (idx >= vec->size()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size()); + return 0; + } + + vec->remove(idx); + + return 1; +} + +// native ArrayDestroy(&Array:which); +static cell AMX_NATIVE_CALL ArrayDestroy(AMX* amx, cell* params) +{ + cell* handle = get_amxaddr(amx, params[1]); + + if (*handle == 0) + { + return 0; + } + + CellArray* vec = HandleToVector(amx, *handle); + + if (vec == NULL) + { + return 0; + } + + delete vec; + + VectorHolder[*handle-1] = NULL; + + *handle = 0; + + return 1; +} + + +struct ArraySort_s +{ + int func; + cell array_hndl; + cell* array_base; + cell array_bsize; + cell data; + cell size; + cell addr1; + cell addr2; + AMX *amx; +}; + +ArraySort_s SortInfo; + +int SortArrayList(const void *elem1, const void *elem2) +{ + return executeForwards( + SortInfo.func, + SortInfo.array_hndl, + ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize, + ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize, + SortInfo.data, + SortInfo.size + ); +} + +// native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0); +static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params) +{ + int handle = params[1]; + CellArray* vec = HandleToVector(amx, handle); + + if (vec == NULL) + { + return 0; + } + + int len; + char* funcName = get_amxstring(amx, params[2], 0, len); + + // MySortFunc(Array:array, item1, item2, const data[], data_size) + int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + if (func < 0) + { + LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); + return 0; + } + + size_t arraysize = vec->size(); + size_t blocksize = vec->blocksize(); + cell *array = vec->base(); + + ArraySort_s oldinfo = SortInfo; + + SortInfo.func = func; + SortInfo.array_base = array; + SortInfo.array_bsize = static_cast(blocksize); + SortInfo.array_hndl = handle; + SortInfo.data = params[3]; + SortInfo.size = params[4]; + + qsort(array, arraysize, blocksize * sizeof(cell), SortArrayList); + + SortInfo = oldinfo; + + unregisterSPForward(func); + + return 1; +} + + +int SortArrayListExCell(const void *elem1, const void *elem2) +{ + size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize; + size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize; + + return executeForwards( + SortInfo.func, + SortInfo.array_hndl, + *&SortInfo.array_base[index1 * SortInfo.array_bsize], + *&SortInfo.array_base[index2 * SortInfo.array_bsize], + SortInfo.data, + SortInfo.size + ); +} + +int SortArrayListExArray(const void *elem1, const void *elem2) +{ + size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize; + size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize; + + cell *addr1 = get_amxaddr(SortInfo.amx, SortInfo.addr1); + cell *addr2 = get_amxaddr(SortInfo.amx, SortInfo.addr2); + + memcpy(addr1, &SortInfo.array_base[index1 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell)); + memcpy(addr2, &SortInfo.array_base[index2 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell)); + + return executeForwards( + SortInfo.func, + SortInfo.array_hndl, + SortInfo.addr1, + SortInfo.addr2, + SortInfo.data, + SortInfo.size + ); +} + +// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0); +static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params) +{ + int handle = params[1]; + CellArray* vec = HandleToVector(amx, handle); + + if (vec == NULL) + { + return 0; + } + + int len; + char* funcName = get_amxstring(amx, params[2], 0, len); + + int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + + if (!func) + { + LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); + return 0; + } + + size_t arraysize = vec->size(); + size_t blocksize = vec->blocksize(); + cell *array = vec->base(); + cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL; + + if (blocksize > 1) + { + int err; + if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE + || ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE) + { + LogError(amx, err, "Ran out of memory"); + return 0; + } + } + + ArraySort_s oldinfo = SortInfo; + + SortInfo.func = func; + SortInfo.array_base = array; + SortInfo.array_bsize = static_cast(blocksize); + SortInfo.array_hndl = params[1]; + SortInfo.data = params[3]; + SortInfo.size = params[4]; + SortInfo.amx = amx; + SortInfo.addr1 = amx_addr1; + SortInfo.addr2 = amx_addr2; + + qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell); + + SortInfo = oldinfo; + + if (blocksize > 1) + { + amx_Release(amx, amx_addr1); + amx_Release(amx, amx_addr2); + } + + unregisterSPForward(func); + + return 1; +} + +extern bool fastcellcmp(cell *a, cell *b, cell len); +extern int amxstring_len(cell* a); + +// native ArrayFindString(Array:which, const item[]); +static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return -1; + } + + cell *b, *a = get_amxaddr(amx, params[2]); + size_t cellcount = vec->blocksize(); + size_t a_len = ke::Max(1, amxstring_len(a)); + size_t len = a_len > cellcount ? cellcount : a_len; + + for (size_t i = 0; i < vec->size(); i++) + { + b = vec->at(i); + + if (fastcellcmp(a, b, len)) + { + return static_cast(i); + } + } + + return -1; +} + +// native ArrayFindValue(Array:which, any:item); +static cell AMX_NATIVE_CALL ArrayFindValue(AMX* amx, cell* params) +{ + CellArray* vec = HandleToVector(amx, params[1]); + + if (vec == NULL) + { + return -1; + } + + for (size_t i = 0; i < vec->size(); i++) + { + if (params[2] == *vec->at(i)) + { + return static_cast(i); + } + } + + return -1; +} + +AMX_NATIVE_INFO g_DataStructNatives[] = +{ + { "ArrayCreate", ArrayCreate }, + { "ArrayClear", ArrayClear }, + { "ArrayClone", ArrayClone }, + { "ArraySize", ArraySize }, + { "ArrayResize", ArrayResize }, + { "ArrayGetArray", ArrayGetArray }, + { "ArrayGetCell", ArrayGetCell }, + { "ArrayGetString", ArrayGetString }, + { "ArraySetArray", ArraySetArray }, + { "ArraySetCell", ArraySetCell }, + { "ArraySetString", ArraySetString }, + { "ArrayPushArray", ArrayPushArray }, + { "ArrayPushCell", ArrayPushCell }, + { "ArrayPushString", ArrayPushString }, + { "ArrayInsertArrayAfter", ArrayInsertArrayAfter }, + { "ArrayInsertCellAfter", ArrayInsertCellAfter }, + { "ArrayInsertStringAfter", ArrayInsertStringAfter }, + { "ArrayInsertArrayBefore", ArrayInsertArrayBefore }, + { "ArrayInsertCellBefore", ArrayInsertCellBefore }, + { "ArrayInsertStringBefore", ArrayInsertStringBefore }, + { "ArraySwap", ArraySwap }, + { "ArrayDeleteItem", ArrayDeleteItem }, + { "ArrayGetStringHandle", ArrayGetStringHandle }, + { "ArrayDestroy", ArrayDestroy }, + { "ArraySort", ArraySort }, + { "ArraySortEx", ArraySortEx }, + { "ArrayFindString", ArrayFindString }, + { "ArrayFindValue", ArrayFindValue }, + + { NULL, NULL } +}; diff --git a/amxmodx/file.cpp b/amxmodx/file.cpp index 8d3c8d3f..6ca02d8d 100755 --- a/amxmodx/file.cpp +++ b/amxmodx/file.cpp @@ -62,7 +62,7 @@ static cell AMX_NATIVE_CALL read_dir(AMX *amx, cell *params) const char* entry = dir->GetEntryName(); cell* outputLen = get_amxaddr(amx, params[5]); - *outputLen = set_amxstring_utf8(amx, params[3], entry, strlen(entry), params[4] + 1); + *outputLen = set_amxstring_utf8(amx, params[3], entry, strlen(entry), params[4]); return offset; } @@ -103,7 +103,7 @@ static cell AMX_NATIVE_CALL read_file(AMX *amx, cell *params) buffer[--length] = '\0'; cell* textLen = get_amxaddr(amx, params[5]); - *textLen = set_amxstring_utf8(amx, params[3], buffer, length, params[4] + 1); // + EOS + *textLen = set_amxstring_utf8(amx, params[3], buffer, length, params[4]); return currentLine; } @@ -624,7 +624,7 @@ static cell AMX_NATIVE_CALL amx_fgets(AMX *amx, cell *params) fp->ReadLine(buffer, sizeof(buffer) - 1); - return set_amxstring_utf8(amx, params[2], buffer, strlen(buffer), params[3] + 1); // + EOS + return set_amxstring_utf8(amx, params[2], buffer, strlen(buffer), params[3]); } // native fseek(file, position, start); @@ -776,7 +776,7 @@ static cell AMX_NATIVE_CALL amx_open_dir(AMX *amx, cell *params) return 0; } - set_amxstring_utf8(amx, params[2], pFirst, strlen(pFirst), params[3] + 1); + set_amxstring_utf8(amx, params[2], pFirst, strlen(pFirst), params[3]); cell* fileType = get_amxaddr(amx, params[4]); *fileType = g_FileSystem->FindIsDirectory(handle) ? FileType_Directory : FileType_File; @@ -798,7 +798,7 @@ static cell AMX_NATIVE_CALL amx_open_dir(AMX *amx, cell *params) } const char* entry = dir->GetEntryName(); - set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3] + 1); + set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3]); return reinterpret_cast(new DirectoryHandle(reinterpret_cast(dir), false)); } @@ -861,7 +861,7 @@ static cell AMX_NATIVE_CALL amx_get_dir(AMX *amx, cell *params) *fileType = g_FileSystem->FindIsDirectory(*handle) ? FileType_Directory : FileType_File; } - set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3] + 1); + set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3]); } else { @@ -887,7 +887,7 @@ static cell AMX_NATIVE_CALL amx_get_dir(AMX *amx, cell *params) const char* entry = handle->GetEntryName(); - set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3] + 1); + set_amxstring_utf8(amx, params[2], entry, strlen(entry), params[3]); } return 1; diff --git a/amxmodx/stackstructs.cpp b/amxmodx/stackstructs.cpp index e414817c..eabd9b22 100644 --- a/amxmodx/stackstructs.cpp +++ b/amxmodx/stackstructs.cpp @@ -184,7 +184,7 @@ static cell AMX_NATIVE_CALL PopStackString(AMX* amx, cell* params) size_t idx = vec->size() - 1; cell *blk = vec->at(idx); - int numWritten = set_amxstring_utf8(amx, params[2], blk, amxstring_len(blk), params[3] + 1); + int numWritten = set_amxstring_utf8(amx, params[2], blk, amxstring_len(blk), params[3]); *get_amxaddr(amx, params[4]) = numWritten; vec->remove(idx); diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index 25503fd7..64275cdd 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -113,9 +113,9 @@ int set_amxstring_utf8(AMX *amx, cell amx_addr, const T *source, size_t sourcele register cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr)); register cell* start = dest; - if (len >= maxlen) + if (len > maxlen) { - len = maxlen - 1; + len = maxlen; needtocheck = true; } @@ -885,8 +885,8 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params) right[right_pos] = 0; left[left_pos] = 0; - set_amxstring_utf8(amx, params[2], left, strlen(left), leftMax + 1); // +EOS - set_amxstring_utf8(amx, params[4], right, strlen(right), rightMax + 1); // +EOS + set_amxstring_utf8(amx, params[2], left, strlen(left), leftMax); + set_amxstring_utf8(amx, params[4], right, strlen(right), rightMax); delete [] left; delete [] right; @@ -960,8 +960,8 @@ static cell AMX_NATIVE_CALL amx_strtok2(AMX *amx, cell *params) right[right_pos] = 0; left[left_pos] = 0; - set_amxstring_utf8(amx, params[2], left, strlen(left), left_max + 1); // + EOS - set_amxstring_utf8(amx, params[4], right, strlen(right), right_max + 1); // + EOS + set_amxstring_utf8(amx, params[2], left, strlen(left), left_max); + set_amxstring_utf8(amx, params[4], right, strlen(right), right_max); delete [] left; delete [] right; @@ -1061,7 +1061,7 @@ do_copy: : end - beg ) : 0; - set_amxstring_utf8(amx, params[2], start, strlen(start), copylen + 1); // + EOS + set_amxstring_utf8(amx, params[2], start, strlen(start), copylen); end = (len-i+1 > (size_t)RightMax) ? (size_t)RightMax : len-i+1; if (end) @@ -1077,7 +1077,7 @@ do_copy: } //if we got here, there was nothing to break - set_amxstring_utf8(amx, params[2], &(string[beg]), strlen(&(string[beg])), LeftMax + 1); // + EOS + set_amxstring_utf8(amx, params[2], &(string[beg]), strlen(&(string[beg])), LeftMax); if (RightMax) *right = '\0'; @@ -1106,13 +1106,13 @@ static cell AMX_NATIVE_CALL split_string(AMX *amx, cell *params) if (strncmp(&text[i], split, splitLen) == 0) { /* Split hereeeee */ - if (i >= maxLen + 1) // + null terminator + if (i > maxLen) { - set_amxstring_utf8(amx, params[3], text, textLen, maxLen + 1); // + null terminator + set_amxstring_utf8(amx, params[3], text, textLen, maxLen); } else { - set_amxstring_utf8(amx, params[3], text, textLen, i + 1); + set_amxstring_utf8(amx, params[3], text, textLen, i); } return i + splitLen; } @@ -1134,7 +1134,7 @@ static cell AMX_NATIVE_CALL format_args(AMX *amx, cell *params) char* string = format_arguments(amx, pos, len); // indexed from 0 - return set_amxstring_utf8(amx, params[1], string, len, params[2] + 1); // + EOS + return set_amxstring_utf8(amx, params[1], string, len, params[2]); } static cell AMX_NATIVE_CALL is_digit(AMX *amx, cell *params) diff --git a/amxmodx/trie_natives.cpp b/amxmodx/trie_natives.cpp index 700d1f38..8d2b4ee4 100644 --- a/amxmodx/trie_natives.cpp +++ b/amxmodx/trie_natives.cpp @@ -213,7 +213,7 @@ static cell AMX_NATIVE_CALL TrieGetString(AMX *amx, cell *params) return 0; } - *pSize = (cell)set_amxstring_utf8(amx, params[3], r->value.chars(), strlen(r->value.chars()), params[4] + 1); // + EOS + *pSize = (cell)set_amxstring_utf8(amx, params[3], r->value.chars(), strlen(r->value.chars()), params[4]); return 1; } @@ -425,7 +425,7 @@ static cell AMX_NATIVE_CALL TrieSnapshotGetKey(AMX *amx, cell *params) } const char *str = snapshot->strings.GetString(snapshot->keys[index]); - return set_amxstring_utf8(amx, params[3], str, strlen(str), params[4] + 1); + return set_amxstring_utf8(amx, params[3], str, strlen(str), params[4]); } //native TrieSnapshotDestroy(&Snapshot:handle) diff --git a/modules/geoip/geoip_natives.cpp b/modules/geoip/geoip_natives.cpp index 993fede0..65528f8b 100644 --- a/modules/geoip/geoip_natives.cpp +++ b/modules/geoip/geoip_natives.cpp @@ -115,7 +115,7 @@ static cell AMX_NATIVE_CALL amx_geoip_country(AMX *amx, cell *params) return MF_SetAmxString(amx, params[2], "error", params[3]); } - return MF_SetAmxStringUTF8Char(amx, params[2], country, length, params[3] + 1); + return MF_SetAmxStringUTF8Char(amx, params[2], country, length, params[3]); } // native geoip_country_ex(const ip[], result[], len, id = -1); @@ -127,7 +127,7 @@ static cell AMX_NATIVE_CALL amx_geoip_country_ex(AMX *amx, cell *params) const char *path[] = { "country", "names", getLang(params[4]), NULL }; const char *country = lookupString(ip, path, &length); - return MF_SetAmxStringUTF8Char(amx, params[2], country ? country : "", length, params[3] + 1); + return MF_SetAmxStringUTF8Char(amx, params[2], country ? country : "", length, params[3]); } // native geoip_city(const ip[], result[], len, id = -1); @@ -139,7 +139,7 @@ static cell AMX_NATIVE_CALL amx_geoip_city(AMX *amx, cell *params) const char *path[] = { "city", "names", getLang(params[4]), NULL }; const char *city = lookupString(ip, path, &length); - return MF_SetAmxStringUTF8Char(amx, params[2], city ? city : "", length, params[3] + 1); + return MF_SetAmxStringUTF8Char(amx, params[2], city ? city : "", length, params[3]); } // native geoip_region_code(const ip[], result[], len); @@ -185,7 +185,7 @@ static cell AMX_NATIVE_CALL amx_geoip_region_name(AMX *amx, cell *params) const char *path[] = { "subdivisions", "0", "names", getLang(params[4]), NULL }; // First result. const char *region = lookupString(ip, path, &length); - return MF_SetAmxStringUTF8Char(amx, params[2], region ? region : "", length, params[3] + 1); + return MF_SetAmxStringUTF8Char(amx, params[2], region ? region : "", length, params[3]); } // native geoip_timezone(const ip[], result[], len); @@ -260,7 +260,7 @@ static cell AMX_NATIVE_CALL amx_geoip_continent_name(AMX *amx, cell *params) const char *path[] = { "continent", "names", getLang(params[4]), NULL }; const char *continent = lookupString(ip, path, &length); - return MF_SetAmxStringUTF8Char(amx, params[2], continent ? continent : "", length, params[3] + 1); + return MF_SetAmxStringUTF8Char(amx, params[2], continent ? continent : "", length, params[3]); }