Add ArraySortEx/SortADTArray natives and new sort method Sort_Random (bug 5494, r=Nextra)
Former-commit-id: 1ff337d9801e2fbd9ad210bc1285d31679b3029e
This commit is contained in:
@ -491,6 +491,10 @@ typedef struct ArraySort_s
|
||||
int forward;
|
||||
cell data;
|
||||
cell size;
|
||||
CellVector *vec;
|
||||
AMX* amx;
|
||||
cell addr1;
|
||||
cell addr2;
|
||||
|
||||
} ArraySort_t;
|
||||
|
||||
@ -577,6 +581,135 @@ static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params)
|
||||
}
|
||||
|
||||
|
||||
int SortArrayListExCell(const void *itema, const void *itemb)
|
||||
{
|
||||
ArraySort_t *Info = ArraySortStack.front();
|
||||
cell vala, valb;
|
||||
|
||||
Info->vec->GetCell(*((int *)itema), &vala);
|
||||
Info->vec->GetCell(*((int *)itemb), &valb);
|
||||
|
||||
return executeForwards(Info->forward, Info->handle, vala, valb, Info->data, Info->size);
|
||||
}
|
||||
|
||||
int SortArrayListExArray(const void *itema, const void *itemb)
|
||||
{
|
||||
ArraySort_t *Info = ArraySortStack.front();
|
||||
|
||||
Info->vec->GetArray(*((int *)itema), get_amxaddr(Info->amx, Info->addr1));
|
||||
Info->vec->GetArray(*((int *)itemb), get_amxaddr(Info->amx, Info->addr2));
|
||||
|
||||
return executeForwards(Info->forward, Info->handle, Info->addr1, Info->addr2, Info->data, Info->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];
|
||||
CellVector* vec=HandleToVector(amx, handle);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell amx_addr1, amx_addr2, *phys_addr = NULL;
|
||||
size_t cellcount = vec->GetCellCount();
|
||||
|
||||
if (cellcount > 1)
|
||||
{
|
||||
int err;
|
||||
if ((err=amx_Allot(amx, cellcount, &amx_addr1, &phys_addr)) != AMX_ERR_NONE
|
||||
|| (err=amx_Allot(amx, cellcount, &amx_addr2, &phys_addr)) != AMX_ERR_NONE)
|
||||
{
|
||||
LogError(amx, err, "Ran out of memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This is kind of a cheating way to go about this but...
|
||||
// Create an array of integers as big as however many elements are in the vector.
|
||||
// Pass that array to qsort
|
||||
// After the array is sorted out, then create a NEW cellvector
|
||||
// and copy in the old data in the order of what was sorted
|
||||
int len;
|
||||
char* FuncName=get_amxstring(amx, params[2], 0, len);
|
||||
// MySortFunc(Array:array, item1, item2, const data[], data_size)
|
||||
int Forward = registerSPForwardByName(amx, FuncName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||
if (Forward < 0)
|
||||
{
|
||||
if (cellcount > 1)
|
||||
{
|
||||
amx_Release(amx, amx_addr1);
|
||||
amx_Release(amx, amx_addr2);
|
||||
}
|
||||
|
||||
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", FuncName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *IntList=new int[vec->Size()];
|
||||
|
||||
for (int i=0; i< vec->Size(); i++)
|
||||
{
|
||||
IntList[i]=i;
|
||||
}
|
||||
|
||||
ArraySort_t *Info=new ArraySort_t;
|
||||
|
||||
Info->handle=handle;
|
||||
Info->forward=Forward;
|
||||
Info->data=params[3];
|
||||
Info->size=params[4];
|
||||
Info->vec = vec;
|
||||
Info->amx = amx;
|
||||
Info->addr1 = amx_addr1;
|
||||
Info->addr2 = amx_addr2;
|
||||
|
||||
ArraySortStack.push(Info);
|
||||
qsort(IntList, vec->Size(), sizeof(int), cellcount > 1 ? SortArrayListExArray : SortArrayListExCell);
|
||||
ArraySortStack.pop();
|
||||
|
||||
CellVector* newvec=new CellVector(vec->GetCellCount());
|
||||
|
||||
// Set the new vector's values
|
||||
for (int i=0; i< vec->Size(); i++)
|
||||
{
|
||||
if (newvec->SetArray(newvec->Push(), vec->GetCellPointer(IntList[i]))!=1)
|
||||
{
|
||||
// This should never happen..
|
||||
LogError(amx, AMX_ERR_NATIVE, "Failed to SetArray in ArraySort (i=%d, IntList=%d)",i,IntList[i]);
|
||||
|
||||
if (cellcount > 1)
|
||||
{
|
||||
amx_Release(amx, amx_addr1);
|
||||
amx_Release(amx, amx_addr2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the old vector
|
||||
delete vec;
|
||||
|
||||
// Now save the new vector in its handle location
|
||||
VectorHolder[handle-1]=newvec;
|
||||
|
||||
// Cleanup
|
||||
delete Info;
|
||||
delete IntList;
|
||||
|
||||
unregisterSPForward(Forward);
|
||||
|
||||
if (cellcount > 1)
|
||||
{
|
||||
amx_Release(amx, amx_addr1);
|
||||
amx_Release(amx, amx_addr2);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||
{
|
||||
@ -603,6 +736,7 @@ AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||
{ "ArrayGetStringHandle", ArrayGetStringHandle },
|
||||
{ "ArrayDestroy", ArrayDestroy },
|
||||
{ "ArraySort", ArraySort },
|
||||
{ "ArraySortEx", ArraySortEx },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
@ -203,6 +203,10 @@ public:
|
||||
cursize=1;
|
||||
count=0;
|
||||
};
|
||||
cell* Base()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
cell* GetCellPointer(size_t which)
|
||||
{
|
||||
if (which >= count)
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "amxmodx.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "datastructs.h"
|
||||
|
||||
/***********************************
|
||||
* About the double array hack *
|
||||
@ -51,6 +53,7 @@ enum SortOrder
|
||||
{
|
||||
Sort_Ascending = 0,
|
||||
Sort_Descending = 1,
|
||||
Sort_Random = 2,
|
||||
};
|
||||
|
||||
int sort_ints_asc(const void *int1, const void *int2)
|
||||
@ -63,17 +66,40 @@ int sort_ints_desc(const void *int1, const void *int2)
|
||||
return (*(int *)int2) - (*(int *)int1);
|
||||
}
|
||||
|
||||
void sort_random(cell *array, cell size)
|
||||
{
|
||||
srand((unsigned int)time(NULL));
|
||||
|
||||
for (int i = size-1; i > 0; i--)
|
||||
{
|
||||
int n = rand() % (i + 1);
|
||||
|
||||
if (array[i] != array[n])
|
||||
{
|
||||
array[i] ^= array[n];
|
||||
array[n] ^= array[i];
|
||||
array[i] ^= array[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL SortIntegers(AMX *amx, cell *params)
|
||||
{
|
||||
cell *array = get_amxaddr(amx, params[1]);
|
||||
cell array_size = params[2];
|
||||
cell type = params[3];
|
||||
|
||||
if (type == Sort_Ascending)
|
||||
if (type == Sort_Ascending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_ints_asc);
|
||||
} else {
|
||||
}
|
||||
else if (type == Sort_Descending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_ints_desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_random(array, array_size);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -118,9 +144,15 @@ static cell AMX_NATIVE_CALL SortFloats(AMX *amx, cell *params)
|
||||
if (type == Sort_Ascending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_floats_asc);
|
||||
} else {
|
||||
}
|
||||
else if (type == Sort_Descending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_floats_desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_random(array, array_size);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -193,9 +225,15 @@ static cell AMX_NATIVE_CALL SortStrings(AMX *amx, cell *params)
|
||||
if (type == Sort_Ascending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_strings_asc);
|
||||
} else {
|
||||
}
|
||||
else if (type == Sort_Descending)
|
||||
{
|
||||
qsort(array, array_size, sizeof(cell), sort_strings_desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_random(array, array_size);
|
||||
}
|
||||
|
||||
/* END HACKHACK - restore what we damaged so Pawn doesn't throw up.
|
||||
* We'll browse through each index of the array and patch up the distance.
|
||||
@ -348,6 +386,98 @@ static cell AMX_NATIVE_CALL SortCustom2D(AMX *amx, cell *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum SortType
|
||||
{
|
||||
Sort_Integer = 0,
|
||||
Sort_Float,
|
||||
Sort_String,
|
||||
};
|
||||
|
||||
int sort_adtarray_strings_asc(const void *str1, const void *str2)
|
||||
{
|
||||
return strcmp((char *) str1, (char *) str2);
|
||||
}
|
||||
|
||||
int sort_adtarray_strings_desc(const void *str1, const void *str2)
|
||||
{
|
||||
return strcmp((char *) str2, (char *) str1);
|
||||
}
|
||||
|
||||
void sort_adt_random(CellVector *cArray)
|
||||
{
|
||||
size_t arraysize = cArray->Size();
|
||||
|
||||
srand((unsigned int)time(NULL));
|
||||
|
||||
for (int i = arraysize-1; i > 0; i--)
|
||||
{
|
||||
int n = rand() % (i + 1);
|
||||
|
||||
cArray->Swap(i, n);
|
||||
}
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL SortADTArray(AMX *amx, cell *params)
|
||||
{
|
||||
CellVector* vec=HandleToVector(amx, params[1]);
|
||||
|
||||
if (vec==NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell order = params[2];
|
||||
|
||||
if (order == Sort_Random)
|
||||
{
|
||||
sort_adt_random(vec);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
cell type = params[3];
|
||||
size_t arraysize = vec->Size();
|
||||
size_t blocksize = vec->GetCellCount();
|
||||
cell *array = vec->Base();
|
||||
|
||||
if (type == Sort_Integer)
|
||||
{
|
||||
if (order == Sort_Ascending)
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_ints_asc);
|
||||
}
|
||||
else
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_ints_desc);
|
||||
}
|
||||
}
|
||||
else if (type == Sort_Float)
|
||||
{
|
||||
if (order == Sort_Ascending)
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_floats_asc);
|
||||
}
|
||||
else
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_floats_desc);
|
||||
}
|
||||
}
|
||||
else if (type == Sort_String)
|
||||
{
|
||||
if (order == Sort_Ascending)
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_adtarray_strings_asc);
|
||||
}
|
||||
else
|
||||
{
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), sort_adtarray_strings_desc);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
AMX_NATIVE_INFO g_SortNatives[] =
|
||||
{
|
||||
{"SortIntegers", SortIntegers},
|
||||
@ -355,6 +485,7 @@ AMX_NATIVE_INFO g_SortNatives[] =
|
||||
{"SortStrings", SortStrings},
|
||||
{"SortCustom1D", SortCustom1D},
|
||||
{"SortCustom2D", SortCustom2D},
|
||||
{"SortADTArray", SortADTArray},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
Reference in New Issue
Block a user