Skip to content

New parameter to FindValueInArray to compare with number of cells #966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions core/logic/smn_adt_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,11 +567,28 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}

for (unsigned int i = 0; i < array->size(); i++)

size_t cellsToCompare = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default value still needs changing here.

Copy link
Contributor Author

@TheDS1337 TheDS1337 Apr 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just built the fork for windows, and did a test.. using this :

#include <sourcemod>

#pragma newdecls required

enum struct SomeBlock		// 3 cells, 12 bytes, different memory representations
{
	int i;
	float f;
	bool b;
}

#define INSTANCE_INT 1337
#define INSTANCE_FLOAT 1337.0
#define INSTANCE_BOOL true

// Almost duplicate to instance1, just to test that it'll fall on this one if I compared the entirety of instance1
#define INSTANCE2_INT INSTANCE_INT
#define INSTANCE2_FLOAT INSTANCE_FLOAT
#define INSTANCE2_BOOL false

#define INSTANCE3_INT 10
#define INSTANCE3_FLOAT 0.0
#define INSTANCE3_BOOL false

ArrayList g_ArrayOfArrays;

public void OnPluginStart()
{
	RegServerCmd("test_create_array", test_create_array);
	RegServerCmd("test_fill_array", test_fill_array);
	RegServerCmd("test_search_array1", test_search_array1);
}

public Action test_create_array(int argc)
{
	const int blockSize = sizeof(SomeBlock); 
	
	g_ArrayOfArrays = new ArrayList(blockSize)
	
	if( g_ArrayOfArrays )
	{
		PrintToServer("Created an array with a block size of: %d", blockSize);
	}
	
	return Plugin_Continue;
}

public Action test_fill_array(int argc)
{
	static SomeBlock instance; instance.i = INSTANCE_INT; instance.f = INSTANCE_FLOAT; instance.b = INSTANCE_BOOL;
	g_ArrayOfArrays.PushArray(instance);
	
	static SomeBlock instance2; instance2.i = INSTANCE2_INT; instance2.f = INSTANCE2_FLOAT; instance2.b = INSTANCE2_BOOL;
	g_ArrayOfArrays.PushArray(instance2);

	static SomeBlock instance3; instance3.i = INSTANCE3_INT; instance3.f = INSTANCE3_FLOAT; instance3.b = INSTANCE3_BOOL;
	g_ArrayOfArrays.PushArray(instance3);
	
	PrintToServer("Added 3 arrays to g_ArrayOfArrays");
	
	return Plugin_Continue;
}

public Action test_search_array1(int argc)
{
	SomeBlock instance;	int pos = -1;	

/////// Search for the first instance,
	instance.i = INSTANCE_INT; 
	instance.f = INSTANCE_FLOAT; 
	instance.b = false;	// modified from "true" to false
	
	PrintToServer("Search for first array using SomeBlock::i and SomeBlock::b");
	
	// The search should start from the very first block because we are comparing the first 2 members (2 cells in this case) only
	if( (pos = g_ArrayOfArrays.FindValue(instance.i, 0, 2)) != -1 )
	{		
		PrintToServer("*	Found it at the position: %d", pos);		// Expectation: pos = 0
	}
	else
	{
		PrintToServer("*	Could not find the array with this pattern.");
	}
	
/////// Search for the third instance
	instance.i = INSTANCE_INT; 
	instance.f = INSTANCE3_FLOAT; // Modified float this time too
	instance.b = INSTANCE3_BOOL;	// modified from "true" to false, so it should fall back on the 3rd item
	
	PrintToServer("Search for third array using SomeBlock::f and SomeBlock::b");
	
	// We do the exact same, except this time we start from the 2nd block
	if( (pos = g_ArrayOfArrays.FindValue(instance.i, 1, 2)) != -1 )
	{		
		PrintToServer("*	Found it at the position: %d", pos);		// Expectation: pos = 2
	}
	else
	{
		PrintToServer("*	Could not find the array with this pattern.");
	}
	
/////// Search for the second instance
	instance.i = INSTANCE2_INT; 
	instance.f = INSTANCE2_FLOAT; 
	instance.b = INSTANCE2_BOOL;	// modified from "true" to false
	
	PrintToServer("Search for second array using SomeBlock::i, SomeBlock::f and SomeBlock::b!");
	
	// We compare the entire structure
	if( (pos = g_ArrayOfArrays.FindValue(instance.i, 0, 0)) != -1 )
	{		
		PrintToServer("*	Found it at the position: %d", pos);		// Expectation: pos = 1
	}
	else
	{
		PrintToServer("*	Could not find the array with this pattern.");
	}
	
	return Plugin_Continue;
}

Output from console:

test_create_array
Created an array with a block size of: 3
test_fill_array
Added 3 arrays to g_ArrayOfArrays
test_search_array1
Search for first array using SomeBlock::i and SomeBlock::b
*       Found it at the position: 0
Search for third array using SomeBlock::f and SomeBlock::b
*       Could not find the array with this pattern.
Search for second array using SomeBlock::i, SomeBlock::f and SomeBlock::b!
*       Found it at the position: 0

It doesn't work, you're right... it could be the memcmp implementation I'm doing is wrong. or it could be that 'instant.i' passed instead of 'instant' in the FindArray functions, from a C perspective I guess its totally okay, but I dunno how SP really handles them, I expect the same.

if (params[0] >= 4)
{
cellsToCompare = (size_t) params[4];
}

if (blocknumber + cellsToCompare > array->blocksize())
{
return pContext->ThrowNativeError("Comparing %d cells (blocksize: %d)", blocknumber + cellsToCompare, array->blocksize());
}

cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);

size_t cells = cellsToCompare > 0 ? cellsToCompare : array->blocksize() - blocknumber;

for (size_t i = 0; i < array->size(); i++)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])

if (memcmp(addr, &blk[blocknumber], sizeof(cell_t) * cells) == 0)
{
return (cell_t) i;
}
Expand Down
8 changes: 5 additions & 3 deletions plugins/include/adt_array.inc
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,11 @@ methodmap ArrayList < Handle {
// value cannot be located, -1 will be returned.
//
// @param item Value to search for
// @param block Optionally which block to search in
// @param block Optionally which block to search in
// @param cellsToCompare Optionally the number of cells to compare, anything below 1 stands for the rest of the cells
// @return Array index, or -1 on failure
// @error Invalid block index
public native int FindValue(any item, int block=0);
public native int FindValue(any item, int block=0, int cellsToCompare=1);

// Retrieve the size of the array.
property int Length {
Expand Down Expand Up @@ -440,10 +441,11 @@ native int FindStringInArray(Handle array, const char[] item);
* @param array Array Handle.
* @param item Value to search for
* @param block Optionally which block to search in
* @param cellsToCompare Optionally the number of cells to compare, anything below 1 stands for the rest of the cells
* @return Array index, or -1 on failure
* @error Invalid Handle or invalid block
*/
native int FindValueInArray(Handle array, any item, int block=0);
native int FindValueInArray(Handle array, any item, int block=0, int cellsToCompare=1);

/**
* Returns the blocksize the array was created with.
Expand Down