Add new options to ArrayList FindString, FindValue (#2216)

This commit is contained in:
Alienmario 2025-11-08 18:03:42 +01:00 committed by GitHub
parent eb3b4d9822
commit 84f67fcd2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 258 additions and 29 deletions

View File

@ -587,29 +587,70 @@ static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
}
// the blocknumber is not guaranteed to always be passed
// The parameters above 2 are optional
size_t blocknumber = 0;
if (params[0] >= 3)
{
blocknumber = (size_t)params[3];
}
if (blocknumber >= array->blocksize())
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}
}
int startidx = -1;
if (params[0] >= 4)
{
startidx = params[4];
if (startidx > 0 && startidx > array->size())
{
return pContext->ThrowNativeError("Invalid start index %d (max: %d)", startidx, array->size());
}
}
bool reverse = false;
if (params[0] >= 5)
{
reverse = params[5];
}
typedef int (*STRCOMPARE)(const char *, const char *);
STRCOMPARE comparefn = (params[0] < 6 || params[6]) ? strcmp : strcasecmp;
char *str;
pContext->LocalToString(params[2], &str);
for (unsigned int i = 0; i < array->size(); i++)
if (reverse)
{
if (startidx < 0)
{
startidx = array->size();
}
for (int i = (startidx - 1); i >= 0; i--)
{
const char *array_str = (const char *)&array->base()[i * array->blocksize() + blocknumber];
if (strcmp(str, array_str) == 0)
if (comparefn(str, array_str) == 0)
{
return (cell_t) i;
}
}
}
else
{
if (startidx < -1)
{
startidx = -1;
}
for (unsigned int i = (startidx + 1); i < array->size(); i++)
{
const char *array_str = (const char *)&array->base()[i * array->blocksize() + blocknumber];
if (comparefn(str, array_str) == 0)
{
return (cell_t) i;
}
}
}
return -1;
}
@ -626,19 +667,41 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
}
// the blocknumber is not guaranteed to always be passed
// The parameters above 2 are optional
size_t blocknumber = 0;
if (params[0] >= 3)
{
blocknumber = (size_t) params[3];
}
blocknumber = (size_t)params[3];
if (blocknumber >= array->blocksize())
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}
}
for (unsigned int i = 0; i < array->size(); i++)
int startidx = -1;
if (params[0] >= 4)
{
startidx = params[4];
if (startidx > 0 && startidx > array->size())
{
return pContext->ThrowNativeError("Invalid start index %d (max: %d)", startidx, array->size());
}
}
bool reverse = false;
if (params[0] >= 5)
{
reverse = params[5];
}
if (reverse)
{
if (startidx < 0)
{
startidx = array->size();
}
for (int i = (startidx - 1); i >= 0; i--)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])
@ -646,6 +709,22 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
return (cell_t) i;
}
}
}
else
{
if (startidx < -1)
{
startidx = -1;
}
for (unsigned int i = (startidx + 1); i < array->size(); i++)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])
{
return (cell_t) i;
}
}
}
return -1;
}

View File

@ -207,19 +207,28 @@ methodmap ArrayList < Handle {
// Returns the index for the first occurrence of the provided string. If
// the string cannot be located, -1 will be returned.
//
// @param item String to search for
// @param block Optionally which block to search in
// @param item String to search for.
// @param block Optionally which block to search in.
// @param start Index to start searching from (exclusive), or -1 for direction default.
// Valid numbers are in the interval [-1..Length].
// @param reverse Whether the search direction should be reversed.
// @param caseSensitive If true (default), comparison is case sensitive.
// If false, comparison is case insensitive.
// @return Array index, or -1 on failure
public native int FindString(const char[] item, int block=0);
// @error Invalid block, or invalid start index.
public native int FindString(const char[] item, int block=0, int start=-1, bool reverse=false, bool caseSensitive=true);
// Returns the index for the first occurrence of the provided value. If the
// value cannot be located, -1 will be returned.
//
// @param item Value to search for
// @param block Optionally which block to search in
// @return Array index, or -1 on failure
// @error Invalid block index
public native int FindValue(any item, int block=0);
// @param item Value to search for.
// @param block Optionally which block to search in.
// @param start Index to start searching from (exclusive), or -1 for direction default.
// Valid numbers are in the interval [-1..Length].
// @param reverse Whether the search direction should be reversed.
// @return Array index, or -1 on failure.
// @error Invalid block, or invalid start index.
public native int FindValue(any item, int block=0, int start=-1, bool reverse=false);
// Sort an ADT Array. Specify the type as Integer, Float, or String.
//

View File

@ -0,0 +1,141 @@
#pragma semicolon 1
#pragma newdecls required
#include <testing>
enum struct TestStruct
{
int intval;
char strval[32];
}
public void OnPluginStart()
{
ArrayList list = new ArrayList(sizeof(TestStruct));
// --------------------------------------------------------------------------------
SetTestContext("EmptyArrayTest");
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, -1, false), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, -1, true), -1);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, -1, false), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, -1, true), -1);
// --------------------------------------------------------------------------------
// Fill
TestStruct ts;
for (int i = 0; i < 10; i++)
{
ts.intval = i;
Format(ts.strval, sizeof(ts.strval), "index%d", i);
list.PushArray(ts);
}
// --------------------------------------------------------------------------------
SetTestContext("FindString");
AssertEq("test_defaults", list.FindString("index3", TestStruct::strval), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, -1, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 0, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 2, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 3, false), -1);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 10, false), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, -1, true), 3);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 0, true), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 3, true), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 4, true), 3);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 10, true), 3);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, -1, false), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, -1, true), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 1, true), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 10, false), -1);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 10, true), 0);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, -1, false), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, -1, true), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 8, false), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 10, false), -1);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 10, true), 9);
AssertEq("test_case_sensitive", list.FindString("INDEX0", TestStruct::strval, .caseSensitive = true), -1);
AssertEq("test_case_sensitive", list.FindString("INDEX0", TestStruct::strval, .caseSensitive = false), 0);
// --------------------------------------------------------------------------------
SetTestContext("FindValue");
AssertEq("test_defaults", list.FindValue(3, TestStruct::intval), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, -1, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 0, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 2, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 3, false), -1);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 10, false), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, -1, true), 3);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 0, true), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 3, true), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 4, true), 3);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 10, true), 3);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, -1, false), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, -1, true), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 1, true), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 10, false), -1);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 10, true), 0);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, -1, false), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, -1, true), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 8, false), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 10, false), -1);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 10, true), 9);
// --------------------------------------------------------------------------------
SetTestContext("IterateOverFindString");
int found, index;
// Duplicate last entry
list.PushArray(ts);
found = 0; index = -1;
while ((index = list.FindString("index9", TestStruct::strval, index, false)) != -1)
{
found++;
}
AssertEq("test_find_all_strings_forward", found, 2);
found = 0; index = -1;
while ((index = list.FindString("index9", TestStruct::strval, index, true)) != -1)
{
found++;
}
AssertEq("test_find_all_strings_reverse", found, 2);
// --------------------------------------------------------------------------------
SetTestContext("IterateOverFindValue");
found = 0, index = -1;
while ((index = list.FindValue(9, TestStruct::intval, index, false)) != -1)
{
found++;
}
AssertEq("test_find_all_values_forward", found, 2);
found = 0; index = -1;
while ((index = list.FindValue(9, TestStruct::intval, index, true)) != -1)
{
found++;
}
AssertEq("test_find_all_values_reverse", found, 2);
// --------------------------------------------------------------------------------
PrintToServer("OK");
}