From c1d737eb95455540e33f090a70645354aa04491f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 May 2018 07:37:17 +0200 Subject: BLI_utildefines: re-ordering array delete macro --- source/blender/blenlib/BLI_utildefines.h | 49 +++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 65dcbf04913..5af97ebb411 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -373,19 +373,48 @@ extern "C" { #define UNPACK4_EX(pre, a, post) UNPACK3_EX(pre, a, post), (pre((a)[3])post) /* array helpers */ -#define ARRAY_LAST_ITEM(arr_start, arr_dtype, tot) \ - (arr_dtype *)((char *)(arr_start) + (sizeof(*((arr_dtype *)NULL)) * (size_t)(tot - 1))) +#define ARRAY_LAST_ITEM(arr_start, arr_dtype, arr_len) \ + (arr_dtype *)((char *)(arr_start) + (sizeof(*((arr_dtype *)NULL)) * (size_t)(arr_len - 1))) -#define ARRAY_HAS_ITEM(arr_item, arr_start, tot) ( \ +#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len) ( \ CHECK_TYPE_PAIR_INLINE(arr_start, arr_item), \ - ((unsigned int)((arr_item) - (arr_start)) < (unsigned int)(tot))) + ((unsigned int)((arr_item) - (arr_start)) < (unsigned int)(arr_len))) + +/** + * \note use faster #ARRAY_DELETE_REORDER_LAST when we can re-order. + */ +#define ARRAY_DELETE(arr, index, delete_len, arr_len) \ + { \ + BLI_assert(((index) >= 0) && ((index) + delete_len <= arr_len)); \ + memmove(&(arr)[index], \ + &(arr)[(index) + (delete_len)], \ + (((arr_len) - (index)) - (delete_len)) * sizeof(*(arr))); \ + } ((void)0) + +/** + * Re-ordering array removal. + * + * When removing single items this compiles down to: + * `if (index + 1 != arr_len) { arr[index] = arr[arr_len - 1]; }` (typical reordering removal), + * with removing multiple items, overlap is detected to avoid memcpy errors. + */ +#define ARRAY_DELETE_REORDER_LAST(arr, index, delete_len, arr_len) \ + { \ + BLI_assert(((index) >= 0) && ((index) + delete_len <= arr_len)); \ + if ((index) + (delete_len) != (arr_len)) { \ + if (((delete_len) == 1) || ((delete_len) <= ((arr_len) - ((index) + (delete_len))))) { \ + memcpy(&(arr)[index], \ + &(arr)[(arr_len) - (delete_len)], \ + (delete_len) * sizeof(*(arr))); \ + } \ + else { \ + memcpy(&(arr)[index], \ + &(arr)[(arr_len) - ((arr_len) - ((index) + (delete_len)))], \ + ((arr_len) - ((index) + (delete_len))) * sizeof(*(arr))); \ + } \ + } \ + } ((void)0) -#define ARRAY_DELETE(arr, index, tot_delete, tot) { \ - BLI_assert(index + tot_delete <= tot); \ - memmove(&(arr)[(index)], \ - &(arr)[(index) + (tot_delete)], \ - (((tot) - (index)) - (tot_delete)) * sizeof(*(arr))); \ - } (void)0 /* assuming a static array */ #if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && !defined(__INTEL_COMPILER) -- cgit v1.2.3