BLI_array: add BLI_array_deduplicate_ordered utility & tests

This commit is contained in:
Campbell Barton 2021-07-09 13:33:36 +10:00
parent ab70133db0
commit 7592a5097c
3 changed files with 83 additions and 0 deletions

View File

@ -44,6 +44,10 @@ void _bli_array_permute(void *arr,
#define BLI_array_permute_ex(arr, arr_len, order, arr_temp) \
_bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp)
unsigned int _bli_array_deduplicate_ordered(void *arr, unsigned int arr_len, size_t arr_stride);
#define BLI_array_deduplicate_ordered(arr, arr_len) \
_bli_array_deduplicate_ordered(arr, arr_len, sizeof(*(arr)))
int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
#define BLI_array_findindex(arr, arr_len, p) _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)

View File

@ -120,6 +120,35 @@ void _bli_array_permute(void *arr,
}
}
/**
* In-place array de-duplication of an ordered array.
*
* \return The new length of the array.
*
* Access via #BLI_array_deduplicate_ordered
*/
unsigned int _bli_array_deduplicate_ordered(void *arr, unsigned int arr_len, size_t arr_stride)
{
if (UNLIKELY(arr_len <= 1)) {
return arr_len;
}
const unsigned int arr_stride_uint = (unsigned int)arr_stride;
uint j = 0;
for (uint i = 0; i < arr_len; i++) {
if ((i == j) || (memcmp(POINTER_OFFSET(arr, arr_stride_uint * i),
POINTER_OFFSET(arr, arr_stride_uint * j),
arr_stride) == 0)) {
continue;
}
j += 1;
memcpy(POINTER_OFFSET(arr, arr_stride_uint * j),
POINTER_OFFSET(arr, arr_stride_uint * i),
arr_stride);
}
return j + 1;
}
/**
* Find the first index of an item in an array.
*

View File

@ -189,3 +189,53 @@ TEST(array_utils, BinaryOrInt4Mix)
BINARY_OR_TEST(data_cmp, data_a, data_b, data_combine, ARRAY_SIZE(data_cmp));
}
#undef BINARY_OR_TEST
/* BLI_array_deduplicate_ordered */
#define DEDUPLICATE_ORDERED_TEST(data, data_cmp) \
{ \
const uint data_len_new = BLI_array_deduplicate_ordered(data, ARRAY_SIZE(data)); \
EXPECT_EQ(data_len_new, ARRAY_SIZE(data_cmp)); \
EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \
/* Ensure running a second time does nothing. */ \
const uint data_len_test = BLI_array_deduplicate_ordered(data, data_len_new); \
EXPECT_EQ(data_len_test, ARRAY_SIZE(data_cmp)); \
EXPECT_EQ_ARRAY(data, data_cmp, data_len_new); \
} \
((void)0)
TEST(array_utils, DeduplicateOrdered1)
{
int data[] = {0};
const int data_cmp[] = {0};
DEDUPLICATE_ORDERED_TEST(data, data_cmp);
}
TEST(array_utils, DeduplicateOrdered2)
{
int data[] = {1, 2};
const int data_cmp[] = {1, 2};
DEDUPLICATE_ORDERED_TEST(data, data_cmp);
}
TEST(array_utils, DeduplicateOrdered2Same)
{
int data[] = {1, 1};
const int data_cmp[] = {1};
DEDUPLICATE_ORDERED_TEST(data, data_cmp);
}
TEST(array_utils, DeduplicateOrdered3Same)
{
int data[] = {1, 1, 1};
const int data_cmp[] = {1};
DEDUPLICATE_ORDERED_TEST(data, data_cmp);
}
TEST(array_utils, DeduplicateOrdered3)
{
int data[] = {3, 3, 2, 2, 1, 1};
const int data_cmp[] = {3, 2, 1};
DEDUPLICATE_ORDERED_TEST(data, data_cmp);
}
#undef DEDUPLICATE_ORDERED_TEST