Add new CellArray natives: Clone/Resize/FindString/FindValue (bug 6104, r=ds)
This commit is contained in:
parent
d6d4badbda
commit
f78fda6d9c
|
@ -82,6 +82,7 @@ static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params)
|
||||||
|
|
||||||
return VectorHolder.size();
|
return VectorHolder.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayClear(Array:which)
|
// ArrayClear(Array:which)
|
||||||
static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
|
static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +97,7 @@ static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArraySize(Array:which)
|
// ArraySize(Array:which)
|
||||||
static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
|
static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +110,54 @@ static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
|
||||||
|
|
||||||
return vec->Size();
|
return vec->Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArrayResize(Array:which, newsize);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayResize(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayClone(Array:which)
|
||||||
|
static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
CellVector* vec = HandleToVector(amx, params[1]);
|
||||||
|
|
||||||
|
if (vec == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellVector *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.size(); ++i)
|
||||||
|
{
|
||||||
|
if (VectorHolder[i] == NULL)
|
||||||
|
{
|
||||||
|
VectorHolder[i] = clonevec;
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorHolder.push_back(clonevec);
|
||||||
|
|
||||||
|
return VectorHolder.size();
|
||||||
|
}
|
||||||
|
|
||||||
// ArrayGetArray(Array:which, item, any:output[]);
|
// ArrayGetArray(Array:which, item, any:output[]);
|
||||||
static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params)
|
static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params)
|
||||||
{
|
{
|
||||||
|
@ -613,7 +663,7 @@ static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell amx_addr1, amx_addr2, *phys_addr = NULL;
|
cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL;
|
||||||
size_t cellcount = vec->GetCellCount();
|
size_t cellcount = vec->GetCellCount();
|
||||||
|
|
||||||
if (cellcount > 1)
|
if (cellcount > 1)
|
||||||
|
@ -711,11 +761,67 @@ static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool fastcellcmp(cell *a, cell *b, cell len);
|
||||||
|
extern int amxstring_len(cell* a);
|
||||||
|
|
||||||
|
// ArrayFindString(Array:which, const item[])
|
||||||
|
static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
int handle = params[1];
|
||||||
|
CellVector* vec = HandleToVector(amx, handle);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell *b, *a = get_amxaddr(amx, params[2]);
|
||||||
|
size_t cellcount = vec->GetCellCount();
|
||||||
|
size_t a_len = max(1, amxstring_len(a));
|
||||||
|
size_t len = a_len > cellcount ? cellcount : a_len;
|
||||||
|
|
||||||
|
for (int i = 0; i < vec->Size(); i++)
|
||||||
|
{
|
||||||
|
b = vec->GetCellPointer(i);
|
||||||
|
|
||||||
|
if (fastcellcmp(a, b, len))
|
||||||
|
{
|
||||||
|
return (cell)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayFindValue(Array:which, any:item);
|
||||||
|
static cell AMX_NATIVE_CALL ArrayFindValue(AMX* amx, cell* params)
|
||||||
|
{
|
||||||
|
int handle = params[1];
|
||||||
|
CellVector* vec = HandleToVector(amx, handle);
|
||||||
|
|
||||||
|
if (!vec)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < vec->Size(); i++)
|
||||||
|
{
|
||||||
|
if (params[2] == *vec->GetCellPointer(i))
|
||||||
|
{
|
||||||
|
return (cell)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
AMX_NATIVE_INFO g_DataStructNatives[] =
|
AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||||
{
|
{
|
||||||
{ "ArrayCreate", ArrayCreate },
|
{ "ArrayCreate", ArrayCreate },
|
||||||
{ "ArrayClear", ArrayClear },
|
{ "ArrayClear", ArrayClear },
|
||||||
|
{ "ArrayClone", ArrayClone },
|
||||||
{ "ArraySize", ArraySize },
|
{ "ArraySize", ArraySize },
|
||||||
|
{ "ArrayResize", ArrayResize },
|
||||||
{ "ArrayGetArray", ArrayGetArray },
|
{ "ArrayGetArray", ArrayGetArray },
|
||||||
{ "ArrayGetCell", ArrayGetCell },
|
{ "ArrayGetCell", ArrayGetCell },
|
||||||
{ "ArrayGetString", ArrayGetString },
|
{ "ArrayGetString", ArrayGetString },
|
||||||
|
@ -737,6 +843,8 @@ AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||||
{ "ArrayDestroy", ArrayDestroy },
|
{ "ArrayDestroy", ArrayDestroy },
|
||||||
{ "ArraySort", ArraySort },
|
{ "ArraySort", ArraySort },
|
||||||
{ "ArraySortEx", ArraySortEx },
|
{ "ArraySortEx", ArraySortEx },
|
||||||
|
{ "ArrayFindString", ArrayFindString },
|
||||||
|
{ "ArrayFindValue", ArrayFindValue },
|
||||||
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,38 @@ private:
|
||||||
size_t cursize; // current size of the vector (maximum elements)
|
size_t cursize; // current size of the vector (maximum elements)
|
||||||
size_t count; // how many units of the vector are in use
|
size_t count; // how many units of the vector are in use
|
||||||
|
|
||||||
|
bool GrowIfNeeded(size_t howmany)
|
||||||
|
{
|
||||||
|
/* Shortcut out if we can store this */
|
||||||
|
if (count + howmany <= cursize)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a base allocation size of 8 items */
|
||||||
|
if (!cursize)
|
||||||
|
{
|
||||||
|
cursize = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's not enough, keep doubling */
|
||||||
|
while (count + howmany > cursize)
|
||||||
|
{
|
||||||
|
cursize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
data = (cell*)realloc(data, (sizeof(cell)* cellcount) * cursize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = (cell*)malloc((sizeof(cell)* cellcount) * cursize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (data != NULL);
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CellVector(): data(NULL), cellcount(0), cursize(0), count(0)
|
CellVector(): data(NULL), cellcount(0), cursize(0), count(0)
|
||||||
{
|
{
|
||||||
|
@ -196,6 +228,34 @@ public:
|
||||||
{
|
{
|
||||||
return this->count;
|
return this->count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool Resize(size_t newsize)
|
||||||
|
{
|
||||||
|
if (newsize <= count)
|
||||||
|
{
|
||||||
|
count = newsize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GrowIfNeeded(newsize - count))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = newsize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellVector *Clone()
|
||||||
|
{
|
||||||
|
CellVector *array = new CellVector(cellcount);
|
||||||
|
array->count = count;
|
||||||
|
array->cursize = cursize;
|
||||||
|
array->data = (cell *)malloc((sizeof(cell)* cellcount) * cursize);
|
||||||
|
memcpy(array->data, data, (sizeof(cell)* cellcount) * count);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
free(data);
|
free(data);
|
||||||
|
|
|
@ -23,14 +23,23 @@ enum Array
|
||||||
*
|
*
|
||||||
* @param cellsize How many cells each entry in the array is.
|
* @param cellsize How many cells each entry in the array is.
|
||||||
* @param reserved How many blank entries are created immediately when the array is created. These entries are not valid to read from until called with ArraySet.
|
* @param reserved How many blank entries are created immediately when the array is created. These entries are not valid to read from until called with ArraySet.
|
||||||
* @return Handle to the array.
|
* @return Handle to the array.
|
||||||
*/
|
*/
|
||||||
native Array:ArrayCreate(cellsize=1, reserved=32);
|
native Array:ArrayCreate(cellsize=1, reserved=32);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones an array, returning a new handle with the same size and data.
|
||||||
|
* You must close it.
|
||||||
|
*
|
||||||
|
* @param which Array handle to be cloned.
|
||||||
|
* @return New handle to the cloned array object on success, 0 on failure.
|
||||||
|
*/
|
||||||
|
native Array:ArrayClone(Array:which);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all entries from the array.
|
* Clears all entries from the array.
|
||||||
*
|
*
|
||||||
* @param which The array to clear.
|
* @param which The array to clear.
|
||||||
* @return 1 on success, 0 on failure.
|
* @return 1 on success, 0 on failure.
|
||||||
*/
|
*/
|
||||||
native ArrayClear(Array:which);
|
native ArrayClear(Array:which);
|
||||||
|
@ -38,16 +47,26 @@ native ArrayClear(Array:which);
|
||||||
/**
|
/**
|
||||||
* Returns the number of elements in the array.
|
* Returns the number of elements in the array.
|
||||||
*
|
*
|
||||||
* @param which The array to check.
|
* @param which The array to check.
|
||||||
* @return How many elements are in the array.
|
* @return How many elements are in the array.
|
||||||
*/
|
*/
|
||||||
native ArraySize(Array:which);
|
native ArraySize(Array:which);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes an array. If the size is smaller than the current size,
|
||||||
|
* the array is truncated.
|
||||||
|
*
|
||||||
|
* @param which Array Handle.
|
||||||
|
* @param newsize New size.
|
||||||
|
* @return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
|
native bool:ArrayResize(Array:which, newsize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns data within an array.
|
* Returns data within an array.
|
||||||
* Make sure the output buffer matches the size the array was created with!
|
* Make sure the output buffer matches the size the array was created with!
|
||||||
*
|
*
|
||||||
* @param which The array to retrieve the item from.
|
* @param which The array to retrieve the item from.
|
||||||
* @param item The item to retrieve (zero-based).
|
* @param item The item to retrieve (zero-based).
|
||||||
* @param output The output buffer to write.
|
* @param output The output buffer to write.
|
||||||
*/
|
*/
|
||||||
|
@ -57,7 +76,7 @@ native ArrayGetArray(Array:which, item, any:output[]);
|
||||||
* Returns a single cell of data from an array.
|
* Returns a single cell of data from an array.
|
||||||
* Use this only with arrays that were created with a cellsize of 1!
|
* Use this only with arrays that were created with a cellsize of 1!
|
||||||
*
|
*
|
||||||
* @param which The array to retrieve the item from.
|
* @param which The array to retrieve the item from.
|
||||||
* @param item The item to retrieve (zero-based).
|
* @param item The item to retrieve (zero-based).
|
||||||
* @return The value of the cell.
|
* @return The value of the cell.
|
||||||
*/
|
*/
|
||||||
|
@ -209,6 +228,26 @@ native ArraySwap(Array:which, item1, item2);
|
||||||
*/
|
*/
|
||||||
native ArrayDeleteItem(Array:which, item);
|
native ArrayDeleteItem(Array:which, item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index for the first occurance of the provided string. If the string
|
||||||
|
* cannot be located, -1 will be returned.
|
||||||
|
*
|
||||||
|
* @param which Array Handle.
|
||||||
|
* @param item String to search for.
|
||||||
|
* @return Array index, or -1 on failure.
|
||||||
|
*/
|
||||||
|
native ArrayFindString(Array:which, const item[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index for the first occurance of the provided value. If the value
|
||||||
|
* cannot be located, -1 will be returned.
|
||||||
|
*
|
||||||
|
* @param which Array Handle.
|
||||||
|
* @param item Value to search for.
|
||||||
|
* @return Array index, or -1 on failure.
|
||||||
|
*/
|
||||||
|
native ArrayFindValue(Array:which, any:item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a handle that is passable to a format compliant routine for printing as a string (with the %a format option).
|
* Creates a handle that is passable to a format compliant routine for printing as a string (with the %a format option).
|
||||||
* It is suggested to pass the function directly as a parameter to the format routine.
|
* It is suggested to pass the function directly as a parameter to the format routine.
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <amxmodx>
|
#include <amxmodx>
|
||||||
|
|
||||||
|
|
||||||
new __testnumber;
|
new __testnumber;
|
||||||
new errcount;
|
new errcount;
|
||||||
new __testfunc[32];
|
new __testfunc[32];
|
||||||
|
@ -25,9 +24,7 @@ new TestWords[6][] = {
|
||||||
"!="
|
"!="
|
||||||
};
|
};
|
||||||
|
|
||||||
|
stock test(any:A,any:B=0,TestType:Type=TT_Equal)
|
||||||
|
|
||||||
stock test(A,B=0,TestType:Type=TT_Equal)
|
|
||||||
{
|
{
|
||||||
++__testnumber;
|
++__testnumber;
|
||||||
|
|
||||||
|
@ -521,6 +518,8 @@ public arraytest9()
|
||||||
test(buff[0],start++);
|
test(buff[0],start++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
showres();
|
showres();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,5 +557,112 @@ public arraytest10()
|
||||||
test(ArrayGetCell(a, i),i+1);
|
test(ArrayGetCell(a, i),i+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
|
||||||
|
public arraytest11()
|
||||||
|
{
|
||||||
|
server_print("Testing cloning function...");
|
||||||
|
|
||||||
|
new Array:a = ArrayCreate(1);
|
||||||
|
|
||||||
|
ArrayPushCell(a, 42);
|
||||||
|
ArrayPushCell(a, 9);
|
||||||
|
ArrayPushCell(a, -1);
|
||||||
|
ArrayPushCell(a, 0);
|
||||||
|
ArrayPushCell(a, 5);
|
||||||
|
ArrayPushCell(a, 10);
|
||||||
|
ArrayPushCell(a, 15);
|
||||||
|
ArrayPushCell(a, 6.5);
|
||||||
|
|
||||||
|
new Array:b = ArrayClone(a);
|
||||||
|
|
||||||
|
ArrayPushCell(b, 48);
|
||||||
|
ArrayPushCell(b, 3.14);
|
||||||
|
|
||||||
|
test(a, b, TT_NotEqual);
|
||||||
|
test(ArraySize(a), ArraySize(b) - 2);
|
||||||
|
test(ArrayGetCell(b, 0), 42);
|
||||||
|
test(ArrayGetCell(b, 2), -1);
|
||||||
|
test(ArrayGetCell(b, 7), 6.5);
|
||||||
|
test(ArrayGetCell(b, 9), 3.14);
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
ArrayDestroy(b);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
|
||||||
|
public arraytest12()
|
||||||
|
{
|
||||||
|
server_print("Testing resizing function...");
|
||||||
|
|
||||||
|
new Array:a = ArrayCreate(16);
|
||||||
|
|
||||||
|
ArrayPushString(a, "egg");
|
||||||
|
|
||||||
|
ArrayResize(a, 50);
|
||||||
|
ArrayPushString(a, "boileregg");
|
||||||
|
|
||||||
|
ArraySetString(a, 50, "no more egg v2");
|
||||||
|
|
||||||
|
new buffer[16];
|
||||||
|
ArrayGetString(a, 50, buffer, charsmax(buffer));
|
||||||
|
|
||||||
|
test(ArraySize(a), 50 + 1);
|
||||||
|
test(strcmp(buffer, "no more egg v2"), 0);
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
|
||||||
|
public arraytest13()
|
||||||
|
{
|
||||||
|
server_print("Testing finding string in array...");
|
||||||
|
|
||||||
|
new Array:a = ArrayCreate(16);
|
||||||
|
|
||||||
|
ArrayPushString(a, "z");
|
||||||
|
ArrayPushString(a, "egg");
|
||||||
|
ArrayPushString(a, "boilerplate");
|
||||||
|
ArrayPushString(a, "amxmodx");
|
||||||
|
ArrayPushString(a, "something");
|
||||||
|
ArrayPushString(a, "");
|
||||||
|
ArrayPushString(a, "eggeggeggeggeggeggegg");
|
||||||
|
|
||||||
|
test(ArrayFindString(a, "egg"), 1);
|
||||||
|
test(ArrayFindString(a, "doh"), -1);
|
||||||
|
test(ArrayFindString(a, "something"), 4);
|
||||||
|
test(ArrayFindString(a, "eggeggeggeggegg"), 6);
|
||||||
|
test(ArrayFindString(a, ""), 5);
|
||||||
|
test(ArrayFindString(a, "zz"), -1);
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
|
showres();
|
||||||
|
}
|
||||||
|
|
||||||
|
public arraytest14()
|
||||||
|
{
|
||||||
|
server_print("Testing finding value in array...");
|
||||||
|
|
||||||
|
new Array:a = ArrayCreate(1);
|
||||||
|
|
||||||
|
ArrayPushCell(a, 2);
|
||||||
|
ArrayPushCell(a, 1);
|
||||||
|
ArrayPushCell(a, 5);
|
||||||
|
ArrayPushCell(a, 3.14);
|
||||||
|
ArrayPushCell(a, -1);
|
||||||
|
|
||||||
|
test(ArrayFindValue(a, -1), 4);
|
||||||
|
test(ArrayFindValue(a, 2), 0);
|
||||||
|
test(ArrayFindValue(a, 3), -1);
|
||||||
|
test(ArrayFindValue(a, 3.14), 3);
|
||||||
|
|
||||||
|
ArrayDestroy(a);
|
||||||
|
|
||||||
showres();
|
showres();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user