glib-aux: add nm_arr_insert_at()/nm_arr_remove_at() helpers

The point is rather special, and the macros themselves are basically
simple wrappers around memmove().

When having a sorted array (for example, a strv array that is searched
using nm_strv_find_binary_search()), then we want to insert/remove
elements at a particular place (via memmove()).

Getting the memmove() arguments is not terribly hard, but hard enough to
add two helper macros for that.
This commit is contained in:
Thomas Haller 2021-08-04 17:48:24 +02:00
parent 2140bbf7f5
commit 622a949ecc
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728

View file

@ -2304,6 +2304,59 @@ int _nm_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *str
/*****************************************************************************/
/* nm_arr_insert_at() does @arr[@idx] = @value, but first memmove's
* the elements @arr[@idx..@len-1] one element up. That means, @arr currently
* has @len valid elements, but it must have space for one more element,
* which will be overwritten.
*
* The use case is to have a sorted array (nm_strv_find_binary_search()) and
* to insert the element at he desired index. The caller must make sure that
* @len is large enough to contain one more element. */
#define nm_arr_insert_at(arr, len, idx, value) \
G_STMT_START \
{ \
typeof(*(arr)) *const _arr = (arr); \
typeof(len) _len = (len); \
typeof(idx) _idx = (idx); \
const gsize _len2 = (_len); \
const gsize _idx2 = (_idx); \
\
nm_assert(_arr); \
nm_assert(_NM_INT_NOT_NEGATIVE(_len)); \
nm_assert(_NM_INT_NOT_NEGATIVE(_idx)); \
nm_assert(_idx <= _len); \
\
if (_idx2 != _len2) \
memmove(&_arr[_idx2 + 1u], &_arr[_idx2], sizeof(_arr[0]) * (_len2 - _idx2)); \
\
_arr[_idx2] = (value); \
} \
G_STMT_END
/* nm_arr_remove_at() removes the element at arr[idx], by memmove'ing
* the elements from arr[idx+1..len-1] down. All it does is one memmove(),
* if there is anything to move. */
#define nm_arr_remove_at(arr, len, idx) \
G_STMT_START \
{ \
typeof(*(arr)) *const _arr = (arr); \
typeof(len) _len = (len); \
typeof(idx) _idx = (idx); \
const gsize _len2 = (_len); \
const gsize _idx2 = (_idx); \
\
nm_assert(_arr); \
nm_assert(_len > 0); \
nm_assert(_NM_INT_NOT_NEGATIVE(_idx)); \
nm_assert(_idx < _len); \
\
if (_idx2 != _len2 - 1u) \
memmove(&_arr[_idx2], &_arr[_idx2 + 1u], sizeof(_arr[0]) * ((_len2 - 1u) - _idx2)); \
} \
G_STMT_END
/*****************************************************************************/
#define NM_UTILS_NSEC_PER_SEC ((gint64) 1000000000)
#define NM_UTILS_USEC_PER_SEC ((gint64) 1000000)
#define NM_UTILS_MSEC_PER_SEC ((gint64) 1000)